【问题标题】:How to avoid implementing methods from abstract class?如何避免实现抽象类的方法?
【发布时间】:2016-04-06 18:03:35
【问题描述】:

为简单起见,假设我有一个“Base”抽象类:

public abstract class BaseClass
{
    public abstract void BaseMethod(object obj);

    public abstract void BaseMethod();
}

我想从这个“BaseClass”继承第二和第三类:

public class Class1 : BaseClass
{
    public override void BaseMethod(object obj)
    {
        //Some code
    }
}

public class Class2 : BaseClass
{
    public override void BaseMethod()
    {
        //Some code
    }
}

基本上,我希望每个类实现一个方法而不实现另一个。上面的例子不起作用,因为对于每个类,我都被提示实现另一个抽象方法。

我知道我可以只实现另一个方法“空”。但是,我试图避免这种情况,因为我发现了以下语句:

可以在不实现抽象方法的情况下继承抽象类(尽管这样的派生类本身就是抽象的)

这个说法有错吗?非常感谢有关此主题的任何意见。谢谢!

【问题讨论】:

  • 为什么要这样做?你想解决什么问题?
  • "(虽然这样的派生类本身是抽象的)" 试图阻止子类实现或覆盖特定的基类方法是徒劳的练习。如果你想让自己痛苦,只需到外面用头撞人行道。
  • 如果您将这些课程设为abstract,就可以了。当然,任何派生自它们但不是abstract 的类都必须实现另一种方法。也许你可以解释为什么你认为你需要这样做,我们可以建议另一种方法。也许你真的想要两个独立的接口,每个接口都定义了这些方法。
  • 很像接口,抽象类可以继承其他抽象类。在这种情况下,派生类当然不能实现基类的任何抽象方法。但是,当您从抽象类继承,并且您的类不是抽象的时,您必须实现所有抽象方法。这就像实现一个从另一个接口派生的接口。

标签: c# inheritance abstract-class


【解决方案1】:

可以在不实现抽象方法的情况下继承抽象类(虽然这样的派生类本身就是抽象的

粗体部分是您不遵守的部分 - 是的,您可以拥有一个仅实现一些抽象方法的“中间”类,但该类也必须是抽象的。在某些时候,当你到达具体类时,必须实现所有抽象方法;要么在类本身中,要么在继承链上的某个地方。

【讨论】:

  • 你有一个错字 - 你写了很多而不是必须。
  • @ZoharPeled 谢谢,已修复。
  • 非常感谢您的意见,我一直在为声明的最后一部分而苦苦挣扎。
【解决方案2】:

该语句没有错,但是要遵循该语句,您的代码需要更改为

public abstract class Class1 : BaseClass
{
    public override void BaseMethod(object obj)
    {
        //Some code
    }
}

public abstract class Class2 : BaseClass
{
    public override void BaseMethod()
    {
        //Some code
    }
}

所以你仍然不能创建类。更好的解决方案是使用空函数或引发错误的函数将函数变为虚拟函数而不是抽象函数。

public abstract class BaseClass
{
    public virtual void BaseMethod(object obj) { throw new NotImplmentedException(); }

    public abstract void BaseMethod() { throw new NotImplmentedException(); }
}

但我仍然认为这是一个坏主意,如果你有一个List<BaseClass>,你怎么知道你想要调用哪个正确的版本?您应该重新考虑您的设计,使其只有一个两个函数都可以使用的虚拟方法。

【讨论】:

    【解决方案3】:

    “可以在不实现抽象方法的情况下继承抽象类(尽管这样的派生类本身就是抽象的)”。

    这个说法是正确的。这意味着如果没有实现所有抽象方法,类“Class1”和“Class2”也必须是抽象类。

    【讨论】:

      【解决方案4】:

      正如其他人所说,你不能。您必须将 BaseClass 划分为两个不同的类(如果 BaseClass 是您的)。

      您可以通过包装或以某种方式扩展 BaseClass 来“作弊”

          public class BaseClassWrapper : BaseClass
          {
              private IBaseMethodA methodA;
      
              private IBaseMethodB methodB;
      
              public BaseClassWrapper(IBaseMethodA methodA, IBaseMethodB methodB)
              {
                  this.methodA = methodA;
                  this.methodB = methodB;
              }
      
              public override void BaseMethod()
              {
                  methodB.BaseMethod();
              }
      
              public override void BaseMethod(object obj)
              {
                  methodA.BaseMethod(obj);
              }
      
              public interface IBaseMethodA
              {
                  void BaseMethod(object obj);
              }
      
              public interface IBaseMethodB
              {
                  void BaseMethod();
              }
          }
      

      现在你有两个独立的接口来实现。 这显然会使设计和实现更加复杂,但可能会给您带来一些优势。例如,如果您有 4 种不同的 IBaseMethodA 实现和 3 种不同的 IBaseMethodB 实现,您可以混合搭配它们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-25
        • 1970-01-01
        • 2013-05-30
        • 1970-01-01
        • 1970-01-01
        • 2016-11-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多