6

我最近在浏览一些开源代码 PicketLink 代码。如果你看一下这个类,你会在一个抽象类中看到许多具体方法,它们什么都不做。这样做有什么目的吗?

我想到了两件事:

  1. 如果该方法需要被子类覆盖而不是在父抽象类中定义,为什么不简单地将其抽象化呢?
  2. 如果实际上只有一些子类需要实现该方法,这是否表明需要重组类层次结构,以免子类被迫拥有不适用的方法?
4

3 回答 3

10

虽然不是最常见的情况,但有时在模板方法的上下文中很方便。在这种情况下,有一个定义流程的方法,将某些部分的具体实现留给它的子类。在某些情况下,默认的具体行为是什么都不做,将基类中的具体方法留空,但允许通过覆盖在子类中进行自定义。

高温高压

于 2012-12-07T21:02:15.417 回答
5

我个人认为这是一种代码气味。

就像您说的那样,除非它们具有某些基本功能-它们没有,否则它们应该是抽象的,从而强制派生类提供实现。

如果某些派生类不应该有这些方法的实现,那么设计可能有问题。

考虑一下:

public abstract class Animal
{
    public abstract string Speak();
}

public class Dog : Animal
{
    public override string Speak()
    {
        Console.WriteLine("Woof");
    }
}

public class Cat : Animal
{
    public override string Speak()
    {
        Console.WriteLine("Meow");
    }
}

到目前为止一切都很好,但是如果你想添加一个不会说话的动物怎么办?

public class Ant : Animal
{
    public override string Speak()
    {
        // do nothing - ants don't speak.
    }
}

在我看来,这很糟糕。有人可能会这样做(你所描述的)。

public abstract class Animal
{
    public string Speak()
    {
        // not abstract because not all derived animals speak.
    }
}

在我看来,这更好,但仍然不是很好。在这种情况下,我希望看到的是将 Speak 移动到一个界面,并且只有会说话的动物才能实现它,或者类似的东西。

public abstract class Animal
{
}

public abstract class Mammal : Animal
{
    public abstract string Speak();
}

public class Dog : Mammal
{
    public override string Speak()
    {
        Console.WriteLine("Woof");
    }
}

public class Cat : Mammal
{
    public override string Speak()
    {
        Console.WriteLine("Meow");
    }
}

public class Ant : Animal
{
}
于 2012-12-07T21:14:02.640 回答
4

根据 Andres Fortier 的回答,您还将在 Swing 中看到很多这种模式,以及各种 EventListener Adapter 类。例如,MouseAdapter为每个监听器方法提供了对应的空方法。这允许接口定义所有相关方法,但实现扩展相应的适配器并且只覆盖他们关心的单个方法,而不是被迫为所有其他接口方法提供空主体。

于 2012-12-07T21:25:15.873 回答