C# (常规类和接口)与抽象类
我最近遇到了一个关于抽象类的问题 抽象类的功能可以通过使用(带受保护构造函数的常规类+接口)的组合来实现 使用抽象类优于(带受保护构造函数+接口的常规类)有什么好处。 IMHO,抽象类的目的是使其具有跨类层次结构可用的公共特性。它可以限制子类通过抽象方法实现某些特征。它可以允许子类重写公共行为 抽象类没有作为具体对象的用途。因此,它不允许实例化抽象类 然而,我们可以使用常规类+接口实现同样的功能C# (常规类和接口)与抽象类,c#,oop,inheritance,abstract-class,C#,Oop,Inheritance,Abstract Class,我最近遇到了一个关于抽象类的问题 抽象类的功能可以通过使用(带受保护构造函数的常规类+接口)的组合来实现 使用抽象类优于(带受保护构造函数+接口的常规类)有什么好处。 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'
}
。。。你为什么要这么做?您的类是一个独特的逻辑实体。你为什么要把它分成两部分:非抽象部分和抽象部分?这只会增加阅读和故障排除的难度。更糟糕的是,类中的代码和抽象声明越多。请不要在没有正当理由的情况下否决投票。我想了解其基本原理。如果问题不正确,我就把它去掉。普通类可以创建自身的实例,抽象类不能。此外,如果向类添加接口,则必须在该类上实现它,不能将实现保留为抽象。因此,您的常规类+接口必须实现该接口才能编译。为什么要跨越所有这些障碍来实现一些已经存在的东西呢?第三点是错误的——你不能强迫一个类既继承实现接口的类,又强迫它实现所有接口方法本身。你所建议的在任何方面都不是一个真正的选项。