Oop 引用父类中的子类的模板
在D中,是否可以从父类中引用子(继承)类 我试过这样的方法:Oop 引用父类中的子类的模板,oop,d,Oop,D,在D中,是否可以从父类中引用子(继承)类 我试过这样的方法: abstract public @property typeof(this)[] sequence(); 希望typeof(this)将解析为重写该方法的子类,而不是父类;但事实并非如此。有办法吗 提前谢谢。听起来像是你在找的 但是,请注意,上面的sequence不是一个虚拟函数,而且模板是在基类的上下文中实例化的。为了向用户提供一个简单的界面,您可能希望转到一个专门的函数。这可以是虚拟函数(在这种情况下,您需要强制转换函数的返回值
abstract public @property typeof(this)[] sequence();
希望typeof(this)
将解析为重写该方法的子类,而不是父类;但事实并非如此。有办法吗
提前谢谢。听起来像是你在找的 但是,请注意,上面的
sequence
不是一个虚拟函数,而且模板是在基类的上下文中实例化的。为了向用户提供一个简单的界面,您可能希望转到一个专门的函数。这可以是虚拟函数(在这种情况下,您需要强制转换函数的返回值),也可以是子类中的duck类型函数:
class Base {
T[] sequence(this T)() {
// Virtual call, requires unsafe cast of return type.
return cast(T[])sequenceImplVirtual();
// Non-virtual call, requires safe cast of this reference
// and will fail if the subclass doesn't implement it correctly.
return (cast(T)this).sequenceImplDuck();
}
abstract Base[] sequenceImplVirtual();
}
class Derived : Base {
Derived[] sequenceImplDuck() {
return [this];
}
override Base[] sequenceImplVirtual() {
return [this];
}
}
unittest {
Derived[] arr = (new Derived).sequence;
}
虚拟调用可能看起来最吸引人,因为如果子类未能实现sequenceImplVirtual
,它会导致编译错误。但是请注意,重写函数并不声明返回一个派生的[]
,如果您错误地返回了基
或其他非派生自派生的
类,则程序将出错。显式强制转换有效地隐藏了这一点。一个稍微详细一点的程序可以测试这一点:
T[] sequence(this T)() {
import std.algorithm.searching : all;
auto result = sequenceImplVirtual();
assert(result.all!((Base a) => a is null || cast(T)a !is null));
return cast(T[])result;
}
如果sequenceImplVirtual
返回无效值,则在运行时会出现易于理解的断言错误
另一方面,duck类型的解决方案并不表示您在使用它之前忘记实现sequenceImplDuck
。但是,由于它只执行安全强制转换(cast(T)this
),编译器保证返回值确实是一个派生的[]
:
class Base {
T[] sequence(this T)() {
return (cast(T)this).sequenceImplDuck();
}
}
class Derived : Base {
// Note: wrong return type.
// Will fail to compile when you call sequence().
Base[] sequenceImplDuck() {
return [this];
}
}
class Derived2 : Base {
// Note: No implementation.
// Will fail to compile when you call sequence().
}
unittest {
Derived[] arr = (new Derived).sequence;
auto d = new Derived2;
auto arr2 = d.sequence;
}
使用
-unittest
编译时,上述操作将失败,但如果您注释掉unittest,或在编译时不使用-unittest
,编译器将不会给出派生的
或派生的2
未正确实现所需函数的指示,虚拟呼叫将使用哪个。听起来像是您在寻找的
但是,请注意,上面的sequence
不是一个虚拟函数,而且模板是在基类的上下文中实例化的。为了向用户提供一个简单的界面,您可能希望转到一个专门的函数。这可以是虚拟函数(在这种情况下,您需要强制转换函数的返回值),也可以是子类中的duck类型函数:
class Base {
T[] sequence(this T)() {
// Virtual call, requires unsafe cast of return type.
return cast(T[])sequenceImplVirtual();
// Non-virtual call, requires safe cast of this reference
// and will fail if the subclass doesn't implement it correctly.
return (cast(T)this).sequenceImplDuck();
}
abstract Base[] sequenceImplVirtual();
}
class Derived : Base {
Derived[] sequenceImplDuck() {
return [this];
}
override Base[] sequenceImplVirtual() {
return [this];
}
}
unittest {
Derived[] arr = (new Derived).sequence;
}
虚拟调用可能看起来最吸引人,因为如果子类未能实现sequenceImplVirtual
,它会导致编译错误。但是请注意,重写函数并不声明返回一个派生的[]
,如果您错误地返回了基
或其他非派生自派生的
类,则程序将出错。显式强制转换有效地隐藏了这一点。一个稍微详细一点的程序可以测试这一点:
T[] sequence(this T)() {
import std.algorithm.searching : all;
auto result = sequenceImplVirtual();
assert(result.all!((Base a) => a is null || cast(T)a !is null));
return cast(T[])result;
}
如果sequenceImplVirtual
返回无效值,则在运行时会出现易于理解的断言错误
另一方面,duck类型的解决方案并不表示您在使用它之前忘记实现sequenceImplDuck
。但是,由于它只执行安全强制转换(cast(T)this
),编译器保证返回值确实是一个派生的[]
:
class Base {
T[] sequence(this T)() {
return (cast(T)this).sequenceImplDuck();
}
}
class Derived : Base {
// Note: wrong return type.
// Will fail to compile when you call sequence().
Base[] sequenceImplDuck() {
return [this];
}
}
class Derived2 : Base {
// Note: No implementation.
// Will fail to compile when you call sequence().
}
unittest {
Derived[] arr = (new Derived).sequence;
auto d = new Derived2;
auto arr2 = d.sequence;
}
当使用
-unittest
编译时,上述操作将失败,但是如果您注释掉unittest,或者在不使用-unittest
的情况下编译,编译器将不会给出派生的
或派生的
没有正确实现所需函数的指示,而虚拟调用会这样做。如果您有一堆子类,一个包含所有这些元素的列表,以及基类的类型,对于每个元素,sequence
会返回什么?每个都有不同的类型?静态类型不是这样工作的。尽管您可以使用标准的多态性方法得到您想要的。你到底想做什么?好吧,这并不是我想做的,但是为了解释,它是有效的:比如说我想要一个像SerializedElement这样的抽象类,XMLElement和JSoneElement从中继承。我希望每个子类都有一个用于返回子元素的方法/属性,这些子元素显然属于同一个类。我将如何(如果这是可能的话)在SerializedElement中实现一个抽象方法,该方法返回子元素的任何类型的数组(XMLElement或JSONElement)?如果您有一堆子类,以及一个包含所有子类的列表,并且其类型为基类,那么您希望每个元素返回什么?每个都有不同的类型?静态类型不是这样工作的。尽管您可以使用标准的多态性方法得到您想要的。你到底想做什么?好吧,这并不是我想做的,但是为了解释,它是有效的:比如说我想要一个像SerializedElement这样的抽象类,XMLElement和JSoneElement从中继承。我希望每个子类都有一个用于返回子元素的方法/属性,这些子元素显然属于同一个类。我将如何(如果这是可能的话)在SerializedElement中实现一个抽象方法,该方法返回子元素的任何类型的数组(XMLElement或JSONElement)?