我正在开发一个具有以下(非常简化)结构的项目:
BaseClass
SubClassA : BaseClass
SubClassB : BaseClass
有一个使用SubClassA
的用户界面(有很多逻辑),然后将其保存到另一个以BaseClass
作为参数的组件,但立即强制转换为SubClassB
的论点。 UI在传递SubClassA
时失败。
用户界面:
MyComponent.Save(subClassA)
Component:
Save(BaseClass baseClass)
{
SubClassB subClassB = (SubClassB)baseClass;
...
当前实现在UI中创建SubClassB的实例并将其传递 - 但它会导致许多代码,例如
SubClassB.Property1 = SubClassA.Property1a
我正在考虑创建一个两个子类将实现的通用接口。这将是很多工作,但我想我可以慢慢平整当前非常深层次的层次结构。重新组织UI或组件以使用其他子类型将与结构不同(尽管许多字段映射)一样多。接口是否采用正确的方法?我觉得可能有些东西我不知道。
答案 0 :(得分:2)
如果SubclassA
和SubclassB
只与Save
的能力相关,那么是,BaseClass
会更好地作为两个子类实现的接口。< / p>
它不会马上解决你的直接问题:组件从基类转换为(错误的)派生类。看起来这里可能有几个级别的重构。我认为修补代码使得组件转换为SubclassA
通过使用它来使用它是浪费的。更改组件使其可以在单一的常见类型上运行将是一个巨大的胜利。
扁平化深层次结构也会带来许多其他好处 - 比如简化它。如果最终会有一些他们都实现的接口,那不一定是坏事。但要注意包装中的大量接口类型。
简而言之,重新设计UI和组件 - 以及任何其他代码 - 只需少量接口即可工作,而不了解实现类,将会带来好处。
答案 1 :(得分:2)
从使用者的角度来看,接口几乎可以完成抽象类可以做的所有事情(主要的例外是类可以将字段公开为byref,而接口无法这样做,并且与类关联的静态成员可以在类名下分组,与接口相关的静态成员必须按不同的名称分组。除非在极少数情况下需要将字段公开为byref,否则抽象类的主要优点在于实现方面。与接口相关的所有功能必须在实现它的每个类中单独提供,即使这样的功能对于实现它的99%的类是通用的。相比之下,如果从抽象类派生的99%的具体类将以相同的方式实现特定的方法,那么抽象类可以定义该方法一次,让派生类继承它而不必任何注意它。这样的优势可能很好,但有一个主要问题:类只能从其他类继承功能。由于接口不包含任何功能,因此可以从任意数量的其他类继承它们。
当一个人定义一个抽象类时,我建议在很多情况下还应该定义一个包含相同公共功能(抽象类应该实现)的接口,并避免使用抽象类类型的变量或参数。这将允许可以从抽象类继承的实现实现这样做带来的易于实现的好处,但也可以定义从其他东西继承的实现。编写一个继承自其他类型的实现会更有效,但如果代码从不在变量,字段或参数声明中使用抽象类类型,那么使用抽象类派生的代码也可以与接口实现一样工作不。
答案 2 :(得分:1)
为什么不在基类中创建Save()
virtual
- 这似乎是一个更好的选择。这样,如果您有任何常见的保存功能,您可以使用它并在派生类中为其提供其他形式 - 称为polymorphism
。
class BaseClass
{
public virtual void Save()
{
//Use this keyword
}
}
class B : BaseClass
{
public override void Save()
{
base.Save();
}
}