假设我有两种类型,它们都是抽象类型的子类型
abstract A
type B <: A
x
y
z
end
type C <: A
x
y
z
w
end
有没有办法创建C
而无需基本上复制/粘贴B
并添加额外的参数?主要问题是B
和C
非常接近,我希望尽可能少的代码重复。我知道手册说混凝土类型不能互为子类型:
Julia的类型系统的一个特别显着特征是具体类型可能不会相互进行子类型化:所有具体类型都是最终类型,并且可能只有抽象类型作为其超类型。
有什么方法吗?
答案 0 :(得分:9)
在这些情况下,我通常更喜欢撰写我的类型。
这是我的意思的一个例子:
abstract A
type B <: A
x
y
z
end
type C <: A
b::B
w
end
请注意C
仍然是A
的子类型,但包含B
的实例作为字段。
您确实无法再访问c.x
,而是必须执行c.b.x
。有一个简单的方法。
假设你有一个功能
function my_func(a::A)
# do something with a.x, a.y, a.z
end
如果my_func
适用于A
的任何子类型,则它只能访问A
所有子类型中通用的字段。在这种情况下,x
,y
和z
。
知道这一点,我还会定义一个特定版本的方法来调度C
的实例,如下所示:
my_func(c::C) = my_func(c.b)
这有点冗长,但您可以轻松地将所有这些函数包含在使用@eval
的元编程for循环中并一次生成所有这些函数。有关详细信息,请参阅docs
答案 1 :(得分:2)
我愿意
type XYZ
x
y
z
end
type B <: A
xyz::XYZ
end
type C <: A
xyz::XYZ
w
end
当然,出于性能原因,我通常使用immutable
以及注释尽可能多的类型。
答案 2 :(得分:1)
我用宏来做(如上面的评论中所述)。子类型保持分离,这通常比子子类型更自然:
abstract A
macro A_fields()
quote
a1
a2
end
end
type B <: A
@A_fields
b1
end
type C <: A
@A_fields
c1
end
主要缺点是当您加入A_fields()
时,您必须手动更改A
的子类型的所有构造函数。