覆盖属性以使它们只读 - 那么setter呢?

时间:2015-05-20 20:18:54

标签: c# inheritance properties polymorphism setter

我在类层次结构中有以下设计目标:

有一个BaseClass定义了一些属性,通常是读/写:

public class Media
{
    public virtual object Content { get; set; }
    public virtual double recordingLength { get; set; }
}

目的是建立一些子类,此属性现在只读:

public class CompactDisk : Media
{
    public override object Content
    { 
        get { return this.getContent(); }
        set { 
               // THERE SHOULDN'T BE A SETTER 
            }
    }

    public override double recordingLength
    { 
        get { return 74; }
        set { 
               // NO SETTER EITHER HERE!
            }
    }
}

我迷失在这里,因为我不知道应该如何实现我的设计意图。

2 个答案:

答案 0 :(得分:8)

一种可能的方法是使用接口

您可以将基本概念拆分为两个界面:

public interface IWritableMedia
{
    object Content { set; }
    double recordingLength { set; }
}

public interface IReadOnlyMedia
{
    object Content { get; }
    double recordingLength { get; }
}

然后CompactDisk之类的内容应该只实现IReadOnlyMedia

public class CompactDisk : IReadOnlyMedia
{
    public object Content { get { return ......; } }
    public double recordingLength { get { return .......; } }
}

如果要实现CD-RW(可重写),则应实现两个接口:

public class RewritableCompactDisk : IReadOnlyMedia, IWritableMedia
{
    public object Content { get; set; }
    public double recordingLength { get; set; }
}

这样您就可以将变量输入为IReadOnlyMediaIWritableMedia

IReadOnlyMedia media = new CompactDisk();
IWritableMedia media2 = new RewritableCompactDisk();

现在问题是IWritableMedia没有提供 getters ,您不希望声明另一个IReadOnlyMedia类型的变量。解决方案是设计一个名为IReadWriteMedia的第三个接口,RewritableCompactDisk应该实现它:

public interface IReadWriteMedia : IReadOnlyMedia, IWritableMedia
{
}

public class RewritableCompactDisk : IReadWriteMedia
{
    public object Content { get; set; }
    public double recordingLength { get; set; }
}

由于IReadWriteMedia实现了IReadOnlyMedia和IWritableMedia,现在您可以使用IReadWriteMedia键入变量并访问getter和setter:

IReadWriteMedia media3 = new RewritableCompactDisk();
object content = media3.Content;
media3.Content = "hello world";

答案 1 :(得分:2)

您不能或者实际上不应该设计子类型“隐藏”基本类型功能的设计。你可以:

  1. 在你的setter中抛出一个NotSupportedException或类似的东西。当您尝试设置无法设置的流的长度时,这就是Stream类的行为。

  2. 更改您的设计。我没有看到一种方法让属性以你想要的方式工作(不使用“隐藏”,恕我直言不是一个好的解决方案),但也许是这样的:

    public interface IMedia
    {
        object Content { get; }
        double RecordingLength { get; }
    }
    
    public interface IWritableMedia : IMedia
    {
        void SetContent(object content);
        void SetRecordingLength(double length);
    }
    
  3. 您的CompactDisk只实现IMedia接口,而HardDrive类可以选择实现IWritableMedia接口。