Ygalbel
Ygalbel

Reputation: 5529

Less visibility in child property c#

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

Answers (2)

Jacek Plesnar
Jacek Plesnar

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

Christopher
Christopher

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

Related Questions