|
|
1
11
我更喜欢将类型设置为泛型:
这确保了编译时的类型安全,而不是将其留给执行时。它还可以防止以下情况:
哎哟
我认为
如果你不想走一般路线,我会引入一个真正的新属性(使用不同的名称)。 |
|
|
2
7
我认为这是一个很好的模式。通过消除强制转换结果的需要,它使显式使用派生类型变得更容易,并且不会“破坏”基类行为。实际上,BCL中的某些类中使用了类似的模式,例如查看DbConnection类层次结构:
因此,如果您通过DbConnection变量操纵连接对象,CreateCommand将返回一个DbCommand;如果通过SqlConnection变量对其进行操作,CreateCommand将返回SqlCommand,如果将其分配给SqlCommand变量,则可以避免强制转换。 |
|
|
3
5
|
|
|
4
3
在我看来,使用“new”关键字对基类隐藏可写属性是个坏主意。new关键字允许您在派生类中隐藏基类的成员,而不是重写它。这意味着使用基类引用对此类成员的调用仍然访问基类代码,而不是派生类代码。C#有'virtual'关键字,它允许派生类实际 override 实现,而不是简单地隐藏它。有一篇相当不错的文章 here 这就是分歧所在。 在您的例子中,看起来您正试图使用方法隐藏作为引入 property covariance 到C#。然而,这种方法存在一些问题。 通常,拥有基类的价值在于允许代码用户以多态方式处理类型。如果有人使用对基类的引用设置传递属性,您的实现会发生什么情况?如果Delivery属性不是ParcelDelivery的实例,派生类是否会中断?对于这种实现选择,您需要问自己以下几类问题。 现在,如果基类中的Delivery属性没有提供setter,那么情况就稍微不同了。基类的用户只能检索属性而不能设置它。由于将属性访问路由回基类,因此通过基类的访问仍然有效。但是,如果派生类未密封,则从派生类继承的类可能会通过使用自己的版本隐藏Delivery属性来引入相同类型的问题。
有一种替代泛型的方法。在您的案例中,您需要考虑是否真的想要一个可设置的属性。如果去掉Delivery属性上的setter,那么使用Order类直接引入的问题就会消失。由于使用构造函数参数设置delivery属性,因此可以保证所有订单都具有正确的策略类型。 |
|
|
5
1
您有什么理由需要更改退货类型吗?如果没有,那么我建议将传递属性设置为虚拟,这样它就必须由继承的类来定义:
如果您确实需要更改返回类型,那么我想知道为什么您需要对返回类型进行如此剧烈的行为更改。不管怎样,如果是这样的话,这对你来说是行不通的。 因此,为了直接回答您的问题,我只会在要求返回类型与基类不同的情况下使用您描述的模式,并且非常谨慎(我会分析我的对象模型,看看是否还有其他我可以先做的事情)。如果不是这样,那么我将使用上面描述的模式。 |
|
|
6
1
考虑这种方法:
然后使用
这还远远不够完美(您的示例没有显示) 为什么? 基类需要完全了解交付策略,使用约束进行泛型更有意义,但这至少允许您对属性使用相同的名称并获得类型安全性。 你的例子中的例子是没有意义的,如果有的话 不 正确的类型不应该用null来屏蔽它,应该抛出,因为您的不变量已被违反。 在可能的情况下,最好使用只读字段。它们清楚地说明了不变性。 |
|
|
7
1
您的解决方案并没有达到您认为的效果。它似乎可以工作,但它不会调用您的“新”方法。考虑下面的代码更改,添加一些输出以查看调用哪种方法:
然后使用以下代码片段实际使用CustomOrder类:
将输出“订单”。新方法特别打破了多态性。它在CustomOrder上创建一个新的Delivery属性,该属性不属于Order基类。因此,当您像使用订单一样使用CustomOrder时,您不会调用新的Delivery属性,因为它只存在于CustomOrder上,不属于Order类。
|
|
|
8
0
使用
|