Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# (常规类和接口)与抽象类_C#_Oop_Inheritance_Abstract Class - Fatal编程技术网

C# (常规类和接口)与抽象类

C# (常规类和接口)与抽象类,c#,oop,inheritance,abstract-class,C#,Oop,Inheritance,Abstract Class,我最近遇到了一个关于抽象类的问题 抽象类的功能可以通过使用(带受保护构造函数的常规类+接口)的组合来实现 使用抽象类优于(带受保护构造函数+接口的常规类)有什么好处。 IMHO,抽象类的目的是使其具有跨类层次结构可用的公共特性。它可以限制子类通过抽象方法实现某些特征。它可以允许子类重写公共行为 抽象类没有作为具体对象的用途。因此,它不允许实例化抽象类 然而,我们可以使用常规类+接口实现同样的功能 将常规类构造函数标记为受保护,这样就不能单独创建对象 提供公共特性的默认实现,并将它们标记为虚拟,以

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

抽象类的功能可以通过使用(带受保护构造函数的常规类+接口)的组合来实现

使用抽象类优于(带受保护构造函数+接口的常规类)有什么好处。

IMHO,抽象类的目的是使其具有跨类层次结构可用的公共特性。它可以限制子类通过抽象方法实现某些特征。它可以允许子类重写公共行为

抽象类没有作为具体对象的用途。因此,它不允许实例化抽象类

然而,我们可以使用常规类+接口实现同样的功能

  • 将常规类构造函数标记为受保护,这样就不能单独创建对象
  • 提供公共特性的默认实现,并将它们标记为虚拟,以防它们需要被子类覆盖
  • 使用接口强制子类实现某些功能
  • 那么,抽象类提供了什么额外的功能呢?


    我想不出别的了。采访者试图了解抽象类与具有受保护构造函数+接口的常规类相比还有哪些好处。

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

    使用抽象类的另一个好处是,您可以简单地将功能添加到抽象类中,而不必担心所有派生类的实现——同样,因为您无法阻止一个类在不从基类派生的情况下实现接口

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


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

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

    不能直接新建抽象类。您可以新建一个常规类+接口,并且不必继承或重写基中的任何内容


    使用抽象类,您可以减少文件的数量,即没有接口,但大多数人可能希望保留这些文件,以便在IoC容器中注册并注入依赖项。

    首先,关于抽象类和接口之间的差异,有许多问题和答案,如:。有很多值得注意的答案。但大多数都是关于编程和语法的

    我想从设计的角度来看:

    我认为抽象类不能扮演接口的角色(+常规类) 在软件设计方面

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

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


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

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

    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"; }
    }
    
    很简单。抽象类有一个函数GetDescription,它依赖于抽象方法getAdexible的存在

    如何使用ProtectedConstructor+接口实现这一点?您不能让嗅觉实现接口(有很多原因,但最大的原因是任何派生类也会继承实现,并且不需要实现任何新的内容),但这意味着它的函数不能引用该方法:

    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);
    }
    
    。。。如果将该类设置为combo 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'
    }
    

    。。。你为什么要这么做?您的类是一个独特的逻辑实体。你为什么要把它分成两部分:非抽象部分和抽象部分?这只会增加阅读和故障排除的难度。更糟糕的是,类中的代码和抽象声明越多。

    请不要在没有正当理由的情况下否决投票。我想了解其基本原理。如果问题不正确,我就把它去掉。普通类可以创建自身的实例,抽象类不能。此外,如果向类添加接口,则必须在该类上实现它,不能将实现保留为抽象。因此,您的常规类+接口必须实现该接口才能编译。为什么要跨越所有这些障碍来实现一些已经存在的东西呢?第三点是错误的——你不能强迫一个类既继承实现接口的类,又强迫它实现所有接口方法本身。你所建议的在任何方面都不是一个真正的选项。