覆盖属性使它们只读 - setter 怎么样?
Overriding properties to make them readonly - what about the setter?
我在 class 层次结构中有以下设计目标:
有一个 BaseClass
定义了一些属性,通常是 read/write:
public class Media
{
public virtual object Content { get; set; }
public virtual double recordingLength { get; set; }
}
目的是要有一些子classes,其中属性现在是只读的:
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!
}
}
}
我在这里迷路了,因为我不知道应该如何实现我的设计意图。
你不能,或者真的不应该,有一个子类型的设计 "hide" 基类型的功能。您可以:
在你的 setter 中抛出一个 NotSupportedException
或类似的。这就是当您尝试设置无法设置的流的长度时 Stream
class 的行为方式。
改变你的设计。我看不到让属性按你想要的方式工作的方法(不求助于 "hiding",恕我直言,这不是一个好的解决方案),但也许是这样的:
public interface IMedia
{
object Content { get; }
double RecordingLength { get; }
}
public interface IWritableMedia : IMedia
{
void SetContent(object content);
void SetRecordingLength(double length);
}
您的 CompactDisk 将只实现 IMedia
接口,而硬盘驱动器 class 可能会选择实现 IWritableMedia
接口。
一种可能的方法是使用接口。
您可以将基本概念拆分为两个界面:
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; }
}
通过这种方式,您可以将变量键入 IReadOnlyMedia
或 IWritableMedia
:
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";
我在 class 层次结构中有以下设计目标:
有一个 BaseClass
定义了一些属性,通常是 read/write:
public class Media
{
public virtual object Content { get; set; }
public virtual double recordingLength { get; set; }
}
目的是要有一些子classes,其中属性现在是只读的:
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!
}
}
}
我在这里迷路了,因为我不知道应该如何实现我的设计意图。
你不能,或者真的不应该,有一个子类型的设计 "hide" 基类型的功能。您可以:
在你的 setter 中抛出一个
NotSupportedException
或类似的。这就是当您尝试设置无法设置的流的长度时Stream
class 的行为方式。改变你的设计。我看不到让属性按你想要的方式工作的方法(不求助于 "hiding",恕我直言,这不是一个好的解决方案),但也许是这样的:
public interface IMedia { object Content { get; } double RecordingLength { get; } } public interface IWritableMedia : IMedia { void SetContent(object content); void SetRecordingLength(double length); }
您的 CompactDisk 将只实现 IMedia
接口,而硬盘驱动器 class 可能会选择实现 IWritableMedia
接口。
一种可能的方法是使用接口。
您可以将基本概念拆分为两个界面:
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; }
}
通过这种方式,您可以将变量键入 IReadOnlyMedia
或 IWritableMedia
:
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";