覆盖属性的访问器

发布于 2024-12-11 06:31:24 字数 1304 浏览 0 评论 0原文

我就直接开始吧。

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

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

I'll just jump right in.

Suppose AudioFile is an abstract class like so:

abstract class AudioFile 
{
    public string Title { get; set; }
}

Now, in most cases, using a.Title is perfectly suited for other classes that inherit from AudioFile. However, in the case of MPEG files, this is stored in a different object in the id3 variable:

class MPEG : AudioFile 
{
    private ID3 id3;

    public new string Title {
        get {
            return id3.Title; 
        }
        set {
            id3.Title = value;
        }
    }
}

class WMA : AudioFile
{

}

What I would like is to do the following:

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.

I would expect the output to be, whether an MPEG or a WMA, the song's title. However, when its MPEG, it doesn't work as expected (because it isn't using the id3 object). The only way it works is:

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.
}

Which is not what I want. And ideas on how to do what I want to do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无语# 2024-12-18 06:31:24

将抽象类属性设为虚拟,以便派生类在需要不同行为时可以重写它。

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# 中,默认情况下成员不是虚拟的。您必须将它们标记为虚拟,并使用override以多态方式替换或增强基本实现。 (对于抽象类中的抽象成员,您可以使用关键字 abstract 而不是 virtual。)当基本方法为不是虚拟的,但你已经看到了它的局限性。

Make the abstract class property virtual so that derived classes can override it if they need different behaviors.

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

In your version, you leave the abstract class property non-virtual and mark the derived class property as new. This allows you to use your custom behavior only via the reference of the derived class. You lose the ability to experience the polymorphic behavior via the base. The new modifier hides the base behavior only through the derived reference. Base references use the base behavior.

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

You may happen to come from a Java background. In C#, members are not virtual by default. You must mark them as virtual, and use override to replace or augment the base implementations in a polymorphic way. (For abstract members in abstract classes, you would use the keyword abstract instead of virtual.) The new keyword is useful when the base method is not virtual, but you have already seen its limitation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文