有struct的继承需求的时候要怎么处理?
struct A
a::Int
end
struct B <: A # 怎么继承
b::int
end
有struct的继承需求的时候要怎么处理?
struct A
a::Int
end
struct B <: A # 怎么继承
b::int
end
还是有点困惑,如果类B和C都拥有一个共同部分A的成员变量,但是有个函数(或者说接口),对A,B,C有同样的操作,就是改变A中某个变量的值,那该如何设计?
大概草稿如下(伪代码)
struct A
a::Int
end
struct B <: A
b::Int
end
struct C <: A
c::Int
end
function f!(obj_a::A)
obj_a.a = 2
end
composition:
abstract type AbstractA end
abstract type AbstractBC <: AbstractA end
mutable struct A <: AbstractA
a::Int
end
mutable struct B <: AbstractBC
a::A
b::Int
end
mutable struct C <: AbstractBC
a::A
c::Int
end
f!(x::AbstractA) = x.a = 2
f!(x::AbstractBC) = f!(x.a)
julia> aa = A(1)
A(1)
julia> bb = B(A(1), 2)
B(A(1), 2)
julia> cc = C(A(1), 3)
C(A(1), 3)
julia> f!(aa); aa
A(2)
julia> f!(bb); bb
B(A(2), 2)
julia> f!(cc); cc
C(A(2), 3)
补充阅读材料(材料中有可能Julia的版本较老,但不影响领悟到其中的意思):
这样确实可行,但是我现在的父类有十几个成员,这样我就要对每个成员写两个函数来对A和B、C公共的成员做设置?
假设:你这个OO本身设计的没有问题
你提到的情况是Composition_over_inheritance设计准则的drawback, 解决方案是用 trait-based dispatch, GitHub - mauro3/SimpleTraits.jl: Simple Traits for Julia
通过你提供的已有信息,我猜你在用Julia移植一些非科学计算相关的代码,注意Julia主要目标用户是做科学计算的,要做通用编程,传统OO最好还是用经典的OO语言。这里不是说Julia不能做,而是做起来要改变设计思路,比较困难。
假设:你这个OO本身设计的就是有问题的
在这种情况下,需要贴出具体代码,并详细解释实际的问题,预期的结果和当前的解决方案,以便大家讨论最佳实现。
我确实是写了非科学计算的代码,因为这些代码以前是python写的,但是现在遇到了性能瓶颈。用C++重写的代价比较大,所以采用Julia来尝试写
能给一些更多的信息吗? 还是代码需要保密?
抱歉,这是公司的代码,我不能拿出来。这个程序大概是一个模拟器,模拟某种物体的运动,这个物体有非常多的属性,也有一些种类(通过继承实现),对于这个物体有公共的动作,但是每个动作对各个种类也有自己额外的操作
class Obj:
def __init__(self):
self.xxx = xxx
...
def f(self):
# actions
...
class ObjA(Obj):
def __init__(self):
super(ObjA, self).__init__()
self.yyy = yyy
...
def f(self):
super(ObjA, self).f()
# other action
...
大体明白了,Obj
里有很多公共属性,然后想用overriding。这样把公共的属性放到Obj
中,子类继承AbstractObj
即可:
julia> abstract type AbstractObj end
julia> mutable struct Obj
a::Int
end
julia> mutable struct A <: AbstractObj
b::Obj
c::Int
end
julia> mutable struct B <: AbstractObj
b::Obj
d::Int
end
julia> f!(x::AbstractObj) = x.b.a = 20 # default
f! (generic function with 1 method)
julia> f!(x::A) = x.b.a = 30
f! (generic function with 2 methods)
julia> xx = Obj(1)
Obj(1)
julia> aa = A(Obj(1), 2)
A(Obj(1), 2)
julia> bb = B(Obj(1), 3)
B(Obj(1), 3)
julia> f!(aa); aa
A(Obj(30), 2)
julia> f!(bb); bb
B(Obj(20), 3)
如果是物体的种类是树形结构,就用abstract type多分几层。
如果我想在外部访问公共部分的成员变量,有什么方式嘛?
正常访问即可:
julia> aa.b.a
1
如果想模拟公共成员变量就在A
中,可以重载Base.getproperty
:
julia> function Base.getproperty(x::AbstractObj, name::Symbol)
if name in fieldnames(Obj) # this assumes all subtypes have a common filed b::Obj
return getfield(x.b, name)
else
return getfield(x, name)
end
end
julia> aa = A(Obj(1), 2)
A(Obj(1), 2)
julia> aa.a
1
# 重载以便自动补全
julia> function Base.propertynames(x::AbstractObj, private::Bool=false)
public = fieldnames(typeof(x))
true ? ((public ∪ fieldnames(Obj))...,) : public
end
julia> aa.
a b c
多谢多谢,问题基本解决了。
不过这样来看其实完全可以模拟出struct继承的