如何将子类传递给 proc 期望父类型的参数?
How can I pass subclass to proc expecting argument of parent type?
可以手动将 seq[Child]
转换为 seq[Parent]
,但也许有更好的选择?
type
ParentRef = ref object of RootObj
a: int
ChildRef = ref object of ParentRef
b: int
let parents = @[ParentRef()]
let children = @[ChildRef()]
proc process(list: seq[ParentRef]): void = discard list
process(parents)
process(children) # <== error
也许更好的选择是使用 generic proc?
type
Parent = object of RootObj
a: int
Child = object of Parent
b: int
let parents = @[Parent(a: 2)]
let children = @[Child(a: 3, b: 5)]
proc process[T: Parent](list: seq[T]): void =
echo repr(list)
echo "Accessing generic attribute a: ", list[0].a
process(parents)
process(children)
事实上,如果您不添加 T : Parent
限制,那么只要编译器在类型上找到它想要的所有字段,proc
就可以用于任何事情:
type
Parent = object of RootObj
a: int
Child = object of Parent
b: int
FooBar = object of RootObj
a: int
bar: string
let parents = @[Parent(a: 2)]
let children = @[Child(a: 3, b: 5)]
let foobars = @[FooBar(a: 42, bar: "Yohoo")]
proc process[T](list: seq[T]): void =
echo repr(list)
echo "Accessing generic attribute a: ", list[0].a
process(parents)
process(children)
process(foobars)
Nim 的类型系统比很多都强大,默认情况下它只根据 these rules.
隐式转换类型
我们可以看到 sub-class 可以转换为其超类,
但是 seq[type1]
只能转换为 seq[type2]
如果 type1==type2
,即它们是相同的,而不是子类型。
再添加一个隐式转换关系,定义一个type-converter,要么case by case:
converter seqChildToSeqParent(c:seq[ChildRef]):seq[ParentRef]= c.mapIt(it.ParentRef)
或一般用于任何子类型:
converter toSeqParent[T:ParentRef](x:seq[T]):seq[ParentRef]= x.mapIt(it.ParentRef)
定义其中一个转换器后,编译器将自动为您转换,调用 process(children)
将进行编译,并且 运行.
可以手动将 seq[Child]
转换为 seq[Parent]
,但也许有更好的选择?
type
ParentRef = ref object of RootObj
a: int
ChildRef = ref object of ParentRef
b: int
let parents = @[ParentRef()]
let children = @[ChildRef()]
proc process(list: seq[ParentRef]): void = discard list
process(parents)
process(children) # <== error
也许更好的选择是使用 generic proc?
type
Parent = object of RootObj
a: int
Child = object of Parent
b: int
let parents = @[Parent(a: 2)]
let children = @[Child(a: 3, b: 5)]
proc process[T: Parent](list: seq[T]): void =
echo repr(list)
echo "Accessing generic attribute a: ", list[0].a
process(parents)
process(children)
事实上,如果您不添加 T : Parent
限制,那么只要编译器在类型上找到它想要的所有字段,proc
就可以用于任何事情:
type
Parent = object of RootObj
a: int
Child = object of Parent
b: int
FooBar = object of RootObj
a: int
bar: string
let parents = @[Parent(a: 2)]
let children = @[Child(a: 3, b: 5)]
let foobars = @[FooBar(a: 42, bar: "Yohoo")]
proc process[T](list: seq[T]): void =
echo repr(list)
echo "Accessing generic attribute a: ", list[0].a
process(parents)
process(children)
process(foobars)
Nim 的类型系统比很多都强大,默认情况下它只根据 these rules.
隐式转换类型我们可以看到 sub-class 可以转换为其超类,
但是 seq[type1]
只能转换为 seq[type2]
如果 type1==type2
,即它们是相同的,而不是子类型。
再添加一个隐式转换关系,定义一个type-converter,要么case by case:
converter seqChildToSeqParent(c:seq[ChildRef]):seq[ParentRef]= c.mapIt(it.ParentRef)
或一般用于任何子类型:
converter toSeqParent[T:ParentRef](x:seq[T]):seq[ParentRef]= x.mapIt(it.ParentRef)
定义其中一个转换器后,编译器将自动为您转换,调用 process(children)
将进行编译,并且 运行.