3

我正在开发一个具有以下(非常简化)结构的项目:

BaseClass

SubClassA : BaseClass
SubClassB : BaseClass

有一个 UI(有很多逻辑)使用SubClassA,然后将其保存到另一个组件,该组件BaseClass作为参数立即将参数转换为SubClassB. 这会失败,因为 UI 正在传入SubClassA

用户界面:

MyComponent.Save(subClassA)

Component:
Save(BaseClass baseClass)
{
SubClassB subClassB = (SubClassB)baseClass;

...

当前的实现在 UI 中创建了一个 SubClassB 的实例并将其传递出去 - 但它会导致大量代码,例如

SubClassB.Property1 = SubClassA.Property1a

我正在考虑创建一个由 2 个子类实现的通用接口。这将是很多工作,但慢慢地我认为我可以扁平化当前非常深的层次结构。重新设计 UI 或组件以使用其他子类型将与结构不同(尽管许多字段映射)一样多的工作。接口方法是正确的方法吗?我觉得我可能缺少一些东西。

4

3 回答 3

2

来自消费者从观点来看,接口几乎可以做抽象类可以做的所有事情(主要的例外是类可以将字段公开为 byref,而接口没有这样做的方法,并且与类关联的静态成员可以分组在类名,与接口相关的静态成员必须以不同的名称分组)。除了在极少数情况下需要将字段公开为 byref 之外,抽象类的主要优势在于实现方面。与接口相关的所有功能都必须在实现它的每个类中单独提供,即使这种功能对于实现它的 99% 的类来说都是通用的。相比之下,如果从抽象类派生的 99% 的具体类将以相同的方式实现特定方法,它' 抽象类可以定义该方法一次,并让派生类继承它,而无需任何注意。这样的优势可能很好,但有一个主要问题:一个类只能从另一个类继承功能。由于接口不包含任何功能,它们可以从任意数量的其他类继承。

当定义一个抽象类时,我建议在许多情况下也应该定义一个包含相同公共功能(抽象类应该实现)的接口,并避免使用抽象类类型的变量或参数。这将允许可以从抽象类继承的实现来实现这样做带来的易于实现的好处,但也可以定义从其他东西继承的实现。编写一个从其他类型继承的实现会更有效,但是如果代码从不在变量、字段或参数声明中使用抽象类类型,那么使用抽象类派生类的代码将与接口实现一样工作不。

于 2013-07-18T15:32:07.453 回答
2

如果SubclassASubclassB仅通过它们的能力相关Save,那么是的,BaseClass作为两个子类都实现的接口会更好。

它不会立即解决您的直接问题:从基类到(错误的)派生类的组件转换。看起来这里可能需要进行多个级别的重构。我认为修补代码以便SubclassA通过制作一个组件来转换为 a 是一种浪费。更改组件以便它可以在单个通用类型上运行将是一个巨大的胜利。

扁平化深层层次结构也会带来许多其他好处——比如让它更简单。如果最终有几个接口都实现了,那不一定是坏事。但是,请注意包中的大量接口类型。

简而言之,在不了解实现类的情况下,重新设计 UI 和组件——以及任何其他代码——以仅根据少数接口工作,将会带来好处。

于 2013-07-18T15:09:40.590 回答
1

为什么不在Save() virtual基类中创建一个 - 这似乎是一个更好的选择。这样,如果您有任何常见的保存功能,您可以使用它并在派生类中赋予它其他形式 - 称为polymorphism.

class BaseClass
{
  public virtual void Save()
  {
    //Use this keyword
  }
}
class B : BaseClass
{
  public override void Save()
  {
    base.Save();
  } 
}
于 2013-07-18T14:58:26.363 回答