我马上就跳进来。
假设AudioFile是一个类似的抽象类:
abstract class AudioFile
{
public string Title { get; set; }
}
现在,在大多数情况下,使用a.Title非常适合从AudioFile继承的其他类。但是,对于MPEG文件,它存储在id3变量中的另一个对象中:
class MPEG : AudioFile
{
private ID3 id3;
public new string Title {
get {
return id3.Title;
}
set {
id3.Title = value;
}
}
}
class WMA : AudioFile
{
}
我想要做的是:
AudioFile a;
if( isMPEG ) {
a = LoadMPEG(); // Returns a new MPEG instance.
} else
if( isWMA ) {
a = LoadWMA(); // Return a new WMA instance.
}
Console.WriteLine( a.Title );
// Other stuff with a.
我希望输出是歌曲的标题,无论是MPEG还是WMA。但是,当它的MPEG时,它不能按预期工作(因为它没有使用id3对象)。它的唯一工作方式是:
if( isMPEG ) {
MPEG a = LoadMPEG(); // Returns a new MPEG instance.
Console.WriteLine( a.Title );
// Other stuff with a.
} else
if( isWMA ) {
WMA a = LoadWMA(); // Return a new WMA instance.
Console.WriteLine( a.Title );
// Other stuff with a.
}
这不是我想要的。关于如何做我想做的事的想法?
答案 0 :(得分:4)
创建抽象类属性virtual
,以便派生类可以在需要不同行为时覆盖它。
abstract class AudioFile
{
public virtual string Title { get; set; }
}
class MpegFile : AudioFile
{
public override string Title { /* your custom getter and setter */ }
}
AudioFile file = new MpegFile();
string title = file.Title; // will use override
在您的版本中,您将抽象类属性保留为非虚拟,并将派生类属性标记为new
。这允许您通过派生类的引用仅使用 自定义行为。您失去了通过基础体验多态行为的能力。 new
修饰符通过派生引用隐藏基本行为 。基本引用使用基本行为。
AudioFile file = new MPEG(); // will use base behavior for non-virtual methods
MPEG file = new MPEG(); // will use derived behavior when non-virtual methods are hidden by new
您可能碰巧来自Java背景。在C#中,默认情况下成员不是虚拟的。您必须将它们标记为virtual
,并使用override
以多态方式替换或扩充基本实现。 (对于抽象类中的抽象成员,您可以使用关键字abstract
而不是virtual
。)当基本方法不是虚拟的时,new
关键字很有用,但您已经看过它限制。