假设我有以下c#类:
abstract class a
{
protected abstract void SomeMethod();
}
abstract class b : a
{
protected abstract override void SomeMethod();
}
class c : b
{
protected override void SomeMethod()
{
}
}
在b中覆盖方法实际上是否有任何意义,因为它可以很容易地写成:
abstract class b : a
{
}
写作b的“首选”方式是什么?如果没有重写覆盖抽象方法或属性的原因,为什么允许它?
答案 0 :(得分:5)
您可能想要允许它的一个原因:它显示意图。它解释了是的,你知道这个方法在基类中是抽象的。我知道,我仍然希望它在这里是抽象的。
这样,如果基类删除了该方法,那么您的抽象类将无法编译,而不仅仅是具体的类(甚至可能不在您的代码中)。
那就是说,这不是一个特别重要的原因......我通常会把它抛弃。
答案 1 :(得分:3)
除了已经说过的话:
override
也可用于声明属性,这些属性未在基类中定义。如果仍然没有实现,它将是一个抽象覆盖。
abstract class b : a
{
[SomeAttribute]
protected abstract override void SomeMethod();
}
答案 2 :(得分:2)
拥有a look at this blog。有时将两者结合起来很有用:
“通常会产生良好的语言设计 在几个明确定义的简单 可以组合的原语 一起直观而聪明 方法。相比之下,语言不佳 设计通常导致许多臃肿 构造不好的 在一起。
“抽象”和“覆盖”关键字 在C#中就是一个很好的例子。 它们都有简单的定义,但是 他们可以结合起来表达更多 复杂的概念也是如此。
假设你有一个类层次结构: C来自B,而B来自 A. A有一个抽象方法Foo()和 粘粘()。这里有两个场景 “抽象覆盖”会出现。 1) 假设B只想实现 Goo(),让C实现Foo()。乙 可以将Foo()标记为“抽象覆盖”。 这清楚地表明了B 识别Foo()在。中声明 基类A,但它期待另一个 派生类来实现它。
2)让我们说B想强迫一个C. 重新实现Foo()而不是使用A的 Foo()的定义。 B将Foo()标记为 都覆盖(这意味着B 识别Foo()在。中声明 基类)和抽象(意思是 B强制派生C类提供 实施;不管那个A. 已经提供了一个实现)。 这出现在我最近的一篇博客中 条目在这里。在那个例子中, A = TextReader,Foo = ReadLine,B = a 辅助类,C =想要的某个类 实现ReadLine()而不是 读()。现在TextReader已经有了 ReadLine()的默认实现 基于Read(),但我们想要去 其他方式。我们想要一个 基于a的Read()的实现 派生类的实现 的ReadLine()。因此B提供了一个 消耗的Read()的实现 ReadLine(),然后标记ReadLine() 作为“抽象覆盖”来强制C来 重新定义ReadLine()而不是拾取 从TextReader中获取一个。
总之,“抽象覆盖”是 很酷,不是因为它还有一个 语言功能来表达一些 复杂的角落案例;这很酷,因为 它不再是一种语言功能。 整洁的部分是你不是真的 需要考虑这一点。您 只使用个别的基本概念 自然而然,复杂的东西 自动结合在一起。“
这是方案1的示例代码:
public abstract class A
{
public abstract void Foo();
public abstract void Goo();
}
public abstract class B : A
{
public abstract override void Foo();
public override void Goo()
{
Console.WriteLine("Only wanted to implement goo");
}
}
public class C : B
{
public override void Foo()
{
Console.WriteLine("Only wanted to implement foo");
}
}
我的方案2示例代码:
public abstract class A
{
public virtual void Foo()
{
Console.WriteLine("A's Foo");
}
public abstract void Goo();
}
public abstract class B : A
{
public abstract override void Foo();
public override void Goo()
{
Console.WriteLine("Only wanted to implement goo");
}
}
public class C : B
{
public override void Foo()
{
Console.WriteLine("Forced to implement foo");
}
}
在你的问题中,代码没有用,但这并不意味着抽象和覆盖组合没用。
答案 3 :(得分:2)
当我实际上并不打算提供实现时,我通常不会重新声明抽象方法 - 原因如下:
答案 4 :(得分:0)
您不需要在b中覆盖SomeMethod()。抽象类声明可以有未定义/抽象方法。当您使用另一个抽象类扩展一个抽象类时,它会隐式地从父级继承任何抽象方法。