C# 声明由子类实现的方法的正确方法是什么?
我创建了一个具有公共方法的父类,但也有一些方法希望由子类实现。i、 e.点击执行方法 实施这一点的正确方式是什么C# 声明由子类实现的方法的正确方法是什么?,c#,inheritance,implementation,icommand,C#,Inheritance,Implementation,Icommand,我创建了一个具有公共方法的父类,但也有一些方法希望由子类实现。i、 e.点击执行方法 实施这一点的正确方式是什么 public Parent { CancelCommand = new RelayCommand(CancelClicked, CancelCanExecute); private void CancelClick(object param) { // Do stuff } } public Child : Parent { priv
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由子类处理
我会用外人吗?还是应该使用接口?如果我在子类中使用override,它不会强迫我实现该方法。我不确定是否应该将父类更改为抽象类,因为它具有非抽象方法等。因此,以下是您的选项: 1.将您的基类声明为
抽象类以及一些方法
这种方法有两个优点:您可以自由地在基类上实现公共方法(也就是说,并非所有方法都需要是抽象的),而任何抽象方法都必须在派生类上重写。有一个计数器点(您可能知道):您不能实例化它。也就是说,你不能这样做:
Base obj = new Base();
但是,您仍然能够做到这一点:
Base obj = new Child();
2.使用接口
您可以声明一些接口来强制类实现一些方法。然而,继承和接口之间的语义是完全不同的。你必须决定哪个最适合你的工作
嗯,您可以选择第一个选项。您需要在父级中指定一个抽象方法:
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();
是的,摘要:
public abstract Parent
{
protected abstract bool CancelCanExecute(object param);
//more stuff
}
它也可以是公共的
,但不能是私有的
现在你不能有一个派生类既不能实现CancelCanExecute
,也不能自己是abstract
,所以要强制进一步的派生类来实现它。你应该定义一个接口,然后你的代码应该只接受实现该接口的对象。虽然使用abstract
并创建公共基类非常诱人,但这种方法(几乎)从定义上来说是错误的(几乎)
在C#和其他不允许多重继承的语言中,创建一个基类只是为了定义一个其他人必须填充的空“骨架”,并强制每个人使用它是非常有限的。每个人都必须从中继承,因此,例如,他们将无法重用自己现有的类层次结构,或者必须创建繁琐的桥或(…)
如果抽象基类只有一个/几个/十几个/一百个抽象方法、事件和属性,那么它应该是一个接口,因为它只定义了“公共需求”
使用公共内容创建新抽象库的唯一合理理由是实际提供默认实现。不过,对于这样的基类,也应该定义一个接口,基类应该实现它,并允许重写,甚至可能将某些内容标记为实际抽象的内容——但您的代码仍然应该通过接口引用所有内容,而不是基类。这样的抽象基础应该是实现者的帮助/快捷方式,而不是强制性的。如果有人想从头开始做任何事情,他将实现接口,并用示例代码忽略基础,而您的代码仍然可以很好地使用它。尽管如此,所有公共代码都可以作为一组在该接口上操作的静态帮助器类提供
抽象基类实际上是需要的,在某些情况下不能用接口代替,例如,当您必须强制派生类具有参数构造函数时,或者您自己必须从某个对象派生时,例如,像WPF Visual、UIElement或DependencyObject一样,微软的设计在这里也有一些缺陷。他们强制从基类派生,这会在许多地方影响到开发人员(例如,EntityFramework中的数据模型对象不是依赖对象等)。尽管如此,我认为他们应该从中抽象出来——从视觉和朋友的角度来看,没有那么多的内部例程无法提升到接口。。我不认为他们这样做仅仅是因为,相反,我认为这是关于性能和减少类型转换/方法调度
请注意,我所说的一切并不完全符合你在问题中提出的内容。在这里,您已经假设“父/基类将处理XYZ”。这意味着,您在一开始就放弃了接口方法。使用接口,您将只定义click和cancelclick必须存在,但您将无法实施/提供“基本实现”。这样的事情你可以做的基础课。因此,我认为您应该采用开放/混合的方法:定义接口,定义静态可重用处理程序,只使用接口,并为一些“懒惰的程序员”提供基类:
这可能看起来非常臃肿,但它是非常开放的定制。尽管有了开放性,几乎没有办法强制每个人都必须使用“ClickableImpl”。有一些方法,但是。。它们将包括更多的膨胀和时间/内存开销,我认为它们现在不值得描述
请记住,要估计谁、如何以及有多少人将在将来使用此代码。如果是一个/两个/五个用途,请坚持使用抽象基础。但是,如果您感觉到有几十个或数百个子实现,那么最好添加一个小膨胀,这样以后可能会节省很多时间。您可以将基本方法设置为abstract
,但是您不会强制子类实现它。为此,仅当子类为abstrac时,才应编写接口
@AndreCalil
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); }
}