AZ.*_*AZ. 108 c# polymorphism
// Cannot change source code
class Base
{
public virtual void Say()
{
Console.WriteLine("Called from Base.");
}
}
// Cannot change source code
class Derived : Base
{
public override void Say()
{
Console.WriteLine("Called from Derived.");
base.Say();
}
}
class SpecialDerived : Derived
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
class Program
{
static void Main(string[] args)
{
SpecialDerived sd = new SpecialDerived();
sd.Say();
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
来自Special Derived.
来自Derived./*这不是预期的*/
从Base调用.
如何重写SpecialDerived类,以便不调用中产阶级"Derived"的方法?
更新:
我想继承Derived而不是Base的原因是Derived类包含许多其他实现.既然我不能在base.base.method()
这里做,我想最好的方法是做到以下几点?
//无法更改源代码
class Derived : Base
{
public override void Say()
{
CustomSay();
base.Say();
}
protected virtual void CustomSay()
{
Console.WriteLine("Called from Derived.");
}
}
class SpecialDerived : Derived
{
/*
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
*/
protected override void CustomSay()
{
Console.WriteLine("Called from Special Derived.");
}
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 89
这是一种糟糕的编程习惯,在C#中是不允许的.这是一个糟糕的编程习惯,因为
grandbase的详细信息是基础的实现细节; 你不应该依赖它们.基类提供了grandbase的抽象覆盖; 你应该使用那种抽象,而不是建立旁路来避免它.
您从您的基础派生,因为您喜欢它的功能,并希望重用和扩展它.如果你不喜欢它的功能并希望解决它而不是使用它,那么你为什么首先从中得到它呢?如果这是您想要使用和扩展的功能,请自己从grandbase中获取.
基础可能需要某些不变量用于安全性或语义一致性目的,这些不变量由基本如何使用grandbase方法的细节维护.允许基类的派生类跳过维护这些不变量的代码可能会使基数陷入不一致,损坏的状态.
Evk*_*Evk 88
只想在这里添加这个,因为人们在很多时间之后仍然会回到这个问题.当然这是不好的做法,但仍然可以(原则上)做作者想要的事情:
class SpecialDerived : Derived
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
var ptr = typeof(Base).GetMethod("Say").MethodHandle.GetFunctionPointer();
var baseSay = (Action)Activator.CreateInstance(typeof(Action), this, ptr);
baseSay();
}
}
Run Code Online (Sandbox Code Playgroud)
Jos*_*dan 10
答案(我知道的不是你想要的)是:
class SpecialDerived : Base
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
Run Code Online (Sandbox Code Playgroud)
事实是,你只与你继承的班级有直接的互动.将该类视为一个层 - 提供与它或其父级功能一样多或少的内容,以及它所希望的派生类.
编辑:
你的编辑工作,但我想我会使用这样的东西:
class Derived : Base
{
protected bool _useBaseSay = false;
public override void Say()
{
if(this._useBaseSay)
base.Say();
else
Console.WriteLine("Called from Derived");
}
}
Run Code Online (Sandbox Code Playgroud)
当然,在实际实现中,您可能会为可扩展性和可维护性做更多这样的事情:
class Derived : Base
{
protected enum Mode
{
Standard,
BaseFunctionality,
Verbose
//etc
}
protected Mode Mode
{
get; set;
}
public override void Say()
{
if(this.Mode == Mode.BaseFunctionality)
base.Say();
else
Console.WriteLine("Called from Derived");
}
}
Run Code Online (Sandbox Code Playgroud)
然后,派生类可以适当地控制父母的状态.
小智 7
为什么不简单地将子类转换为特定的父类并调用特定的实现呢?这是一种特殊情况,应该使用特殊情况解决方案.但是,您必须new
在children方法中使用关键字.
public class SuperBase
{
public string Speak() { return "Blah in SuperBase"; }
}
public class Base : SuperBase
{
public new string Speak() { return "Blah in Base"; }
}
public class Child : Base
{
public new string Speak() { return "Blah in Child"; }
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Child childObj = new Child();
Console.WriteLine(childObj.Speak());
// casting the child to parent first and then calling Speak()
Console.WriteLine((childObj as Base).Speak());
Console.WriteLine((childObj as SuperBase).Speak());
}
}
Run Code Online (Sandbox Code Playgroud)
小智 7
public class A
{
public int i = 0;
internal virtual void test()
{
Console.WriteLine("A test");
}
}
public class B : A
{
public new int i = 1;
public new void test()
{
Console.WriteLine("B test");
}
}
public class C : B
{
public new int i = 2;
public new void test()
{
Console.WriteLine("C test - ");
(this as A).test();
}
}
Run Code Online (Sandbox Code Playgroud)