2011-10-21 53 views
3

我就跳右覆盖一个属性的访问器

假设的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. 
} 

这不是我想要的。关于如何做我想做的事情的想法?

回答

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关键字很有用,但您已经看到它的局限性。

+0

很棒的回答,像一个魅力工作。谢谢!是的,我确实来自Java背景。 :) –