假设我有一个成员int number
的A类,它有一个getter和一个setter。
然后我创建一个A的子类并将其称为B.现在,在BI类中希望保留成员number
,但是在这个类中我想强加number
读取的限制 - 只要。我怎么能这样做?
答案 0 :(得分:8)
对此的需求通常暗示您的设计不是最优的(因为它违反了Liskov替代原则)。因此,C#并不真正支持它。但是,以下是种类实现它的两种方法:
(1)隐藏后代中的属性并提供替换基类的getter的新属性。但这并没有真正保护属性,因为你可以只转换到基类:
class A
{
public int Number { get; set; }
}
class B : A
{
public new int Number
{
get { return base.Number; }
}
}
B b = new B();
// b.Number = 42; // This does not work.
A a = b;
a.Number = 42;
Console.WriteLine(b.Number); // == 42. Oops.
(2)用异常抛出覆盖setter。但错误的用法现在导致运行时错误而不是编译器错误,这是不好的。考虑向基础添加bool CanSetNumber
属性(.NET与Stream.CanSeek
和Seek
类似。)
class A
{
public virtual int Number { get; set; }
}
class B : A
{
public override int Number
{
get { return base.Number; }
set { throw new InvalidOperationException("B.Number is readonly!"); }
}
}
B b = new B();
b.Number = 42; // BAM!
答案 1 :(得分:2)
我同意塞巴斯蒂安的回答。另一个需要考虑的选择是使用通用接口而不是直接继承
public interface IHasNumber
{
int Number { get; }
}
public class A : IHasNumber
{
public int Number { get; set; }
}
public class B : IHasNumber
{
public int Number { get; }
}
如果您想共享这些值,则必须将A
封装在B
中。
public class B : IHasNumber
{
public B(A data) { this.Data = data; }
private A Data { get; private set; }
public int Number { get { Data.Number; } }
}
用作
{
var A = new A();
A.Number = 100; // ok
var B = new B(A);
B.Number = 200; // error
Console.WriteLine(B.Number); // prints 100
}