(常规类+接口)vs抽象类

时间:2018-01-14 11:08:58

标签: c# oop inheritance abstract-class

我最近遇到了关于抽象类的问题。

抽象类的功能可以通过使用(Regular class with Protected Constructor + interface)的组合来实现。

使用Abstract Class over(带有受保护构造函数+接口的Regular类)有什么好处。

恕我直言,抽象类的目的是具有需要在类层次结构中可用的共同特征。它可以对子类施加限制,以通过抽象方法实现某些特征。它可以允许子类覆盖常见行为。

Abstract Class不用作具体对象的目的。因此,它不允许实例化抽象类。

但是,我们可以使用Regular Class +接口实现相同的功能。

  1. 将常规类构造函数标记为受保护,因此无法单独创建对象
  2. 提供常用功能的默认实现,并将它们标记为虚拟,以防它们需要被子类覆盖。
  3. 使用界面强制子类实现某些功能。
  4. 那么,Abstract类是否提供了额外的功能?

    我想不出任何其他的。采访者试图了解Abstract类对带有受保护构造函数+接口的Regular Class有什么其他好处。

4 个答案:

答案 0 :(得分:1)

很多很好的理由。让我们从一个明确的开始:

public abstract class Smell
{
    public abstract string GetAdjective();
    public string GetDescription()
    {
        return "I smell " + GetAdjective();
    }
}
public class NastySmell : Smell
{
    public override string GetAdjective() { return "really nasty"; }
}

非常简单。抽象类有一个函数Ge​​tDescription - 它依赖于抽象方法GetAdjective的存在。

你怎么能用ProtectedConstructor + Interface做到这一点?你无法拥有Smell实现接口(出于很多原因,但很重要的是,任何派生类也会继承实现,并且不需要实现任何新的) - 但这意味着它的功能不能参考方法:

public interface SmellInterface
{
    string GetAdjective();
}
public class Smell
{
    protected Smell() { }
    public string GetDescription()
    {
        // how do I call GetAdjective here?  I have no reference to it!
    }
}

但这是另一个更令人信服的理由:

public abstract class SomeFancyClass
{
    protected string name;
    protected string server;
    protected abstract string implementer { get; }
    public string Generate()
    {
        if (name == "something")
            HandleGlobally(name);
        else
            HandleSpecifically(name);
    }
    public void HandleGlobally(string server)
    {
        // code
    }
    public abstract void HandleSpecifically(string server);
}

...如果你让这个类成为一个组合的ProtectedConstructorClass +接口,你将代码分成两个独立的位置 - 突然之间,你必须通过两半看看才能全面了解正在发生的事情!

public interface AbstractHalf
{
    // data property of 'implementer'
    // method of 'HandleSpecifically()
}
public class NonabstractHalf
{
    // data fields of 'name' and 'server'
    // methods of 'Generate()' and 'HandleGlobally'
}

...你为什么要这样做?你的班级是一个独特的逻辑实体。为什么要将它分成两个独立的部分:非抽象的和抽象的?它只是让你更难阅读和排除故障。而且它变得更糟,在课堂上制作的代码和抽象声明越多。

答案 1 :(得分:0)

我能想到的一件事是,通过使用抽象类,您可以通过不将方法或属性标记为virtual来强制执行特定实现,而使用接口则无法阻止类实现接口但不是从您的基类派生的。

使用抽象类的另一个好处是,您可以简单地向抽象类添加功能,而不必担心所有派生类的实现 - 再次,因为您不能阻止类实现接口而不从派生类派生你的基类。

此外,抽象类可以具有受保护的字段,方法,事件等,但是接口不能。

这一切都归结为这样一个事实,即您不能强制实现您的接口的类派生自您的“常规”基类。

答案 2 :(得分:0)

抽象类的主要好处是强制开发人员创建一个继承自抽象类的子类,以便使用基本/共享功能和字段。

你不能直接新建一个抽象类。你可以新建一个普通的类+接口,你不会被迫继承或覆盖基础中的任何东西。

使用抽象类,您可以减少文件数量 - 即没有接口,但大多数人可能希望保留那些用于注册IoC容器和依赖注入。

答案 3 :(得分:-1)

首先,关于抽象类和接口之间的差异有很多问题和答案,例如:this。有很多非凡的答案。但其中大部分都是关于编程和语法的。

我想从设计透视:

来看

我认为抽象类无法发挥接口的作用(+常规类)  在软件设计中。

抽象类:
抽象类的主要目标是抽象原则。为了克服这种复杂性,抽​​象类用于在类似外观类中创建层次结构。层次结构中的所有类都扩展了基类功能和扩展基类类型。

界面:
但是,接口用于类之间的交互。这些类可以相似或不相同。它们可以来自不同的层次结构和不同的类型。

,它们与类(甚至是抽象类)的继承实现接口之间存在巨大差异。接口不是 TYPES 。它们是共享边界,计算机系统的两个或多个单独组件交换信息。