Reputation: 1218
Let's say I have the class A with member int number
which has a getter and a setter.
Then I make a subclass of A and call it B. Now in the class B I wish to keep the member number
, but in this class I want to impose the restriction that number
is read-only. How can I do this?
Upvotes: 1
Views: 214
Reputation: 29244
I agree with Sebastian's answer. Another option to consider is to use a common interface instead of direct inheritance
public interface IHasNumber
{
int Number { get; }
}
public class A : IHasNumber
{
public int Number { get; set; }
}
public class B : IHasNumber
{
public int Number { get; }
}
If you want to share the values then you must encapsulate A
in B
.
public class B : IHasNumber
{
public B(A data) { this.Data = data; }
private A Data { get; private set; }
public int Number { get { Data.Number; } }
}
To be used as
{
var A = new A();
A.Number = 100; // ok
var B = new B(A);
B.Number = 200; // error
Console.WriteLine(B.Number); // prints 100
}
Upvotes: 3
Reputation: 12215
The need for that is usually a hint that your design is not optimal (as it violates the Liskov substitution principle). Therefore, C# does not really support it. However, here are two ways to kind of implement it:
(1) Hide the property in the descendent and provide a new property that replaces the getter of the base class. But this does not really protect the property, since you can just cast to the base class:
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) Override the setter with an exception throw. But a wrong usage now causes a runtime error instead of a compiler error which is not nice. Consider adding a bool CanSetNumber
property to the base (.NET does something similar with Stream.CanSeek
and 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!
Upvotes: 8