如果某些方法不会被使用/未实现,请使用接口或抽象类?

时间:2011-02-12 02:35:28

标签: c# .net interface abstract-class

我有一个项目,其中将抽象地定义相当多的函数和变量getter。我的问题是我应该使用一个抽象类(每个函数抛出NotImplementedException),还是应该只使用一个接口?或者我应该同时使用两者,既可以创建接口,又可以实现接口的抽象类?

注意,即使可以定义所有这些功能等,但这并不意味着它们将全部用于所有用例。例如,身份验证类中的AddUser可以在界面中定义,但由于封闭式用户注册而不会在网站中使用。

7 个答案:

答案 0 :(得分:2)

一般来说,通过这种方式思考,可以回答是否使用继承或接口的问题:

  

在考虑假设时   实现类,是一个案例   这些类型我在哪里   描述,或者是一个案例   这些类型可以可以我所做的   描述

例如,考虑IEnumerable<T>接口。实现IEnumerable<T>的类都是不同的类。他们可以是一个可枚举的结构,但它们基本上是别的东西(List<T>Dictionary<TKey, TValue>或查询等。)

另一方面,请查看System.IO.Stream课程。虽然从该抽象类继承的类是不同的(例如FileStreamNetworkStream),但它们都是基本流 - 只是不同的类。流功能是定义这些类型的核心,而不仅仅是描述它们提供的一部分类型或一组行为。

通常你会觉得两者兼顾是有益的;定义一个定义行为的接口,然后定义一个实现它并提供核心功能的抽象类。如果合适的话,这将允许您充分利用这两个领域:从功能是核心时继承的抽象类,以及在不是核心时继承的接口。

另外,请记住,通过使用扩展方法,仍然可以在接口上提供一些核心功能。虽然严格来说,这并没有在界面上放置任何实际的实例代码(因为这是不可能的),你可以模仿它。这是LINQ-to-Objects查询函数在IEnumerable<T>上的工作方式,通过定义用于查询泛型Enumerable实例的扩展方法的静态IEnumerable<T>类。

作为旁注,您不需要抛出任何NotImplementedException个。如果将函数或属性定义为abstract,那么您不需要(事实上,不能)在抽象类中为它提供函数体;继承类将被强制提供方法体。 他们可能会抛出这样的异常,但这不是你需要担心的事情(并且接口也是如此)。

答案 1 :(得分:1)

如果您未提供任何实现,则使用接口,否则使用抽象类。如果某些方法可能无法在子类中实现,那么创建一个中间抽象类来执行抛出NotSupportedException或类似方法的工作可能是有意义的。

答案 2 :(得分:1)

就个人而言,我认为这取决于“类型”的定义。

如果您要定义一组行为,我会推荐一个界面。

另一方面,如果类型确实定义了“类型”,那么我更喜欢抽象类。我建议保留抽象方法而不是提供空行为。


  

注意,即使可以定义所有这些功能等,但这并不意味着它们将全部用于所有用例。

如果这是真的,您应该考虑将其分解为多个抽象类或接口。在基类/接口中使用“不合适”的方法确实违反了Liskov Substitution Principle,并且是设计缺陷的标志。

答案 3 :(得分:1)

抽象类的一个优点是可以向抽象类添加新的类成员,其默认实现可以用现有的类成员表示,而不会破坏该类的现有继承者。相反,如果将任何新成员添加到接口,则必须修改该接口的每个实现以添加必要的功能。

如果.net允许接口包含未使用对象字段的属性,方法和事件的默认实现,那将是非常好的。从技术角度来看,我认为通过为每个接口提供一个默认vtable条目列表可以毫不费力地完成这样的事情,这些条目可以用于没有定义所有vtable槽的实现。不幸的是,.net中没有类似的能力。

答案 4 :(得分:0)

当您可以提供部分实现时,应该使用抽象类。如果您不想提供任何实现,请使用接口 - 只需定义。

在你的问题中,听起来似乎没有实现,所以请使用界面。

此外,您应该使用NotImplementedException关键字声明您的方法/属性,而不是抛出abstract,以便所有继承者都必须提供实现。

答案 5 :(得分:0)

在某些情况下有效的另一种模式是创建一个非抽象的基类。它有一组定义API的公共方法。这些中的每一个都调用一个Overctedable的Protected方法。 这允许派生类选择它需要实现的方法。 所以例如

 public void AddUser(object user)
    {
        AddUserCore(user);
    }

    protected virtual void AddUserCore(object user)
    {
        //no implementation in base
    }

答案 6 :(得分:0)

@Earlz我想参考这个:Note, even though all of these functions and such may be defined, it does not mean they will all be used in all use cases.与“攻击”这个问题的最佳方式直接相关。

你应该瞄准的是最小化这些功能的数量,使它变得无关紧要(或者至少不那么重要)如果你使用或者。所以尽可能地改进设计,你会发现你走哪条路并不重要。

更好的是发布你正在尝试做的高水平,让我们看看我们是否可以提出一些不错的东西。努力实现共同目标的更多大脑将获得更好的答案/设计。