声明由子类实现的方法的正确方法是什么?

时间:2012-08-28 17:43:01

标签: c# inheritance implementation icommand

我创建了一个具有常用方法的父类,但是我希望子类可以实现这些方法。即单击执行方法。

实施此方法的正确方法是什么?

public Parent {
    CancelCommand = new RelayCommand(CancelClicked, CancelCanExecute);
    private void CancelClick(object param) {
        // Do stuff
    }
}

public Child : Parent {
    private bool CancelCanExecute(object param) {
        // Do stuff
        return true;
    }
}

其中CancelClick由父类托管,而CancelCanExecute由子类处理。

我会使用extern吗?或者我应该使用接口?如果我在子类中使用override,则不会强迫我必须实现该方法。我不确定我是否应该将父类更改为抽象类,因为它具有非抽象方法等等。

4 个答案:

答案 0 :(得分:4)

所以,这是您的选择:

1。将您的基类声明为abstract以及一些方法

这种方法有两个好处:您可以自由地在基类上实现常用方法(也就是说,并非所有方法都需要abstract),而任何抽象方法都必须< / strong>在派生类中重写。有一个反点(您可能知道):您无法实例化它。也就是说,你不能做类似的事情:

Base obj = new Base();

但是,您仍然可以这样做:

Base obj = new Child();

2. 使用接口

您可以声明一些接口来强制您的类实现某些方法。但是,继承和接口之间的语义是完全不同的。你必须决定哪一个最适合你。

恕我直言,你可以选择第一个选项。

答案 1 :(得分:3)

您需要在Parent中指定一个抽象方法:

public abstract class Parent
{
    public void DoSomething()
    {
        // Do something here...
    }

    public abstract void ForceChildToDoSomething();
}

这迫使孩子实施它:

public class Child : Parent
{
    public override void ForceChildToDoSomething()
    {
        // Do something...
    }
}

但是,您现在将拥有一个抽象的父级。因此,如果您想使用Parent中的功能,您需要执行以下操作:

Parent parent = new Child();
parent.DoSomething();
parent.ForceChildToDoSomething();

答案 2 :(得分:1)

是的,摘要:

public abstract Parent
{
  protected abstract bool CancelCanExecute(object param);
  //more stuff
}

它也可以是public,但不是private

现在你不能拥有一个既不实现CancelCanExecute也不实现abstract的派生类,因此迫使进一步的派生类实现它。

答案 3 :(得分:1)

您应该定义一个接口,然后您的代码应该只接受实现该接口的对象。虽然使用abstract并创建一个公共基类非常诱人,但这种方法(几乎)根据定义(几乎)是错误的(差不多)。

在C#和其他不允许多重继承的语言中,创建一个基类只是为了定义其他人必须填充的空“骨架”并迫使每个人使用它非常有限。每个人都必须从中继承,因此,例如,他们将无法重用自己现有的类层次结构,或者必须创建繁琐的桥梁或(...)。

如果你的抽象基类只有一个/几个/十几个/百个抽象方法,事件和属性 - 它应该是一个接口,因为它只定义了'常见要求'。

创建具有常见内容的新抽象基础的唯一合理理由是实际提供默认实现。仍然,使用这样的基类,也应该定义一个接口,基础应该实现它并允许覆盖甚至标记某些实际上是抽象的东西 - 但是你的代码仍然应该通过接口引用所有东西,而不是基类。这样的抽象基础应该是实现者的帮助/捷径,而不是强制性的。如果有人想从头开始做所有事情 - 他将实现接口并忽略带有示例代码的基础,并且您的代码仍然可以很好地使用它。尽管如此,所有公共代码都可以作为一组在这些接口上运行的静态帮助程序类提供。

实际上需要抽象基类,并且在某些极端情况下不能用接口取代,例如,当您必须强制派生类具有参数构造函数时,或者您自己必须从某些东西派生时,即。比如WPF Visual或UIElement或DependencyObject ---因此微软的设计也存在缺陷。它们强制从基类派生,并且它在许多地方遇到开发人员(例如,来自EntityFramework的数据模型对象不是DependencyObjects等)。尽管如此,我认为他们应该从中抽象出来 - 看着视觉和朋友,没有那么多内部例程无法被提升到界面......我不认为他们只是'因为',而是我认为它是关于表现和削减演员/方法派遣。

请注意,我所说的一切并不完全符合您在问题中提出的内容。在那里,您已经假设“父/基类将处理XYZ”。这意味着,您刚刚从界面方法中退出。使用界面,您将只定义该单击并取消单击必须存在,但您将无法强制/提供“基础实现”。你可以用base clases做的事情。因此,我认为您应该采用开放/混合方法:定义接口,定义静态可重用处理程序,仅使用接口,并为某些“懒惰编码器”提供基类:

public interface IClickable
{
    ICommand CancelCommand { get; }
    void CancelClick();
    bool CanCancelClick();
}

public static class ClickableDefaultImpl
{
    public static void DefaultCancelClick(IClickable obj)
    {
        ... do the common things on the OBJ
    }
    public static bool DefaultCanCancelClick(IClickable obj)
    {
        ... do the common things on the OBJ
    }
}

public abstract class Clickable : IClickable
{
    public void CancelClick() { ClickableDefaultImpl.CancelClick(this); }
    public bool CanCancelClick() { return ClickableDefaultImpl.CanCancelClick(this);  }
}

这可能看起来非常臃肿,但它对于定制非常开放。尽管有开放性,但几乎没有办法强制每个人都必须使用“ClickableImpl”。有一些方法,但是......它们会包含更多的膨胀和时间/内存开销,我认为它们现在不值得描述。

请记住估计将来使用此代码的人数,方式和数量。如果是一个/两个/五个用途,坚持使用抽象基础。但是如果你感觉到几十个或几百个子实现,你最好添加一点臃肿 - 它可能会节省很多时间。