我有一个项目,其中将抽象地定义相当多的函数和变量 getter 。我的问题是我应该为此使用一个抽象类(每个函数都会抛出 NotImplementedException),还是应该使用一个接口(interface)?或者我应该同时使用两者,创建一个接口(interface),然后创建一个实现该接口(interface)的抽象类?
请注意,尽管可以定义所有这些函数等,但这并不意味着它们都会在所有用例中使用。例如,身份验证类中的 AddUser 可能在接口(interface)中定义,但由于封闭的用户注册而从未在网站中使用。
最佳答案
一般来说,要不要使用继承或接口(interface)的问题的答案可以这样思考:
When thinking about hypothetical implementing classes, is it a case where these types are what I'm describing, or is it a case where these types can be or can do what I'm describing?
例如,考虑 IEnumerable<T>
界面。实现 IEnumerable<T>
的类都是不同的类(class)。它们可以是一个可枚举的结构,但它们本质上是其他东西(List<T>
或Dictionary<TKey, TValue>
或查询等)
另一方面,看看 System.IO.Stream
类(class)。虽然从该抽象类继承的类不同(例如 FileStream
与 NetworkStream
),但它们本质上都是流 - 只是类型不同。流功能是定义这些类型的核心,而不是仅仅描述类型的一部分或它们提供的一组行为。
通常你会发现两者都做是有益的;定义一个定义您的行为的接口(interface),然后定义一个实现它并提供核心功能的抽象类。如果合适的话,这将使您能够两全其美:当功能是核心时可以继承一个抽象类,当功能不是核心时可以实现一个接口(interface)。
此外,请记住,仍然可以通过使用扩展方法在接口(interface)上提供一些核心功能。严格来说,虽然这并没有在界面上放置任何实际的实例代码(因为这是不可能的),但您可以模仿它。这就是 LINQ-to-Objects 查询函数在 IEnumerable<T>
上的工作方式。 ,通过静态 Enumerable
定义用于查询泛型 IEnumerable<T>
的扩展方法的类实例。
顺便说一句,您不需要抛出任何 NotImplementedException
s。如果将函数或属性定义为 abstract
,那么你不需要(事实上也不能)在抽象类中为其提供函数体;继承类将被迫提供方法体。 它们可能会抛出这样的异常,但这不是您需要担心的事情(对于接口(interface)也是如此)。
关于c# - 当某些方法不会被使用/不实现时,使用接口(interface)还是抽象类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4975953/