Reputation: 5529
I have a base class with a public property.
public class Parent
{
public string Name {get; set;}
}
I want that field will be calculated in the child constructor
public class Child1 : Parent
{
public Child1(string a, string b)
{
this.Name = a + " " + b;
}
}
And I want to mask or decrease visibility of Name
in the child.
That we will not be able to do
var l = new Child1("aa", "bb");
l.Name = "something else";
I am pretty sure that what I am trying to achieve is impossible and against Liskov substitution principle.
Any idea about this?
Upvotes: 0
Views: 312
Reputation: 505
Why not passing name to Parent constructor like that?
public class Parent
{
public string Name { get; private set; } // private set; can be skipped
public class Parent(string name)
{
Name = name;
}
}
Then Child class would look like this
public class Child : Parent
{
public Child(string a, string b)
: base(a + b)
{ }
}
If you are not able to make change in base class there is alternative solution (partially only)
public class Parent
{
public string Name { get; set; }
}
public class Child : Parent
{
public new string Name
{
get => base.Name;
private set => base.Name = value;
}
public Child(string a, string b)
{
Name = $"{a} {b}";
}
}
But there is quick workaround for encapsulation...
Child c = new Child("abc", "def");
c.Name = "New name"; // this will cause compilation error
Parent p = c; // this is perfectly legal
p.Name = "HACKED!";
Upvotes: 1
Reputation: 9824
This sounds less like a parent/child relationship or another case of Polymorphy. I do not know of a accesor that would say "public in this class, but not inheritors". And not just for C#, but any OOP langauge I learned.
It sounds more like a a case for encapsulation:
public class Child1 {
Parent _backingField; //Set in constructor
public string ParentName {
get { return _backingField.Name; }
//No setter
}
}
One of the first things you learn in MVVM: If polymorphy can not do that or you do not have enough control over the class, just encapsulate it into something you do have full control over.
Edit: In a more advanced view, with a abstract base class:
public abstract class Person {
public string Name {get; set;}
}
public class Parent : Person {
//I know of no property parent could have, that person does not
//Even the concept of a parent name, sounds more like a "Person" thing
}
public class Child1 : Person {
Parent _backingField; //Set in constructor
public string ParentName {
get { return _backingField.Name; }
//No setter
}
}
Alternatively, just make one class:
public class Person {
//Every person has a parent
Person _backingField; //Set in constructor
public string ParentName {
get { return _backingField.Name; }
//No setter
}
//And of course it's own name
public string Name {get; set;}
}
Upvotes: 1