0

Code example first:

public class Child1 : Parent
{
    private int _value;
    public int Value => _value;

    public void Initialize(Random random)
    {
        base.Initialize();
        _value = random.Next(1,100);
    }
}

public class Child2 : Parent
{
    private double _value;
    public double Value => _value;

    public void Initialize(Random random)
    {
        base.Initialize();
        _value = random.NextDouble();
    }
}

public class Parent
{
    private bool _initialized;
    private string _id;
    public string Id => _id;

    protected void Initialize()
    {
        if(!_initialized) 
        {
            _id = System.Guid.NewGuid().ToString();
        }
    }
}

What I want to do:

class Program
{
    private Parent[] _things = new Parent[] {new Child1(), new Child2(), new Child1()}
    private Random _random = new Random();

    static void Main(string[] args)
    {
        foreach (var thing in _things)
        {
            thing.Initialize(_random);    
        }
    }
}

But this code doesn't work, because it tries to call the protected initialize instead of the child class initialize. As I have read in this question you can not cast an object to its child class from the parent class.

I feel like logically, this type of construct makes sense, because the parent class can hold all the common fields and logic, while the children have the differences, and do different things in their own initialization methods. I want to handle the mixed bunch of child classes easily in an array and call their initialize function. And there should never exist a parent class that is initialized on its own.

Am I doing something fundamentally wrong and is there a different approach to this kind of construct, that would let me call the initialize method of a bunch of different child classes?

I would really appreciate a working code example.

Deckweiss
  • 29
  • 7
  • 4
    did you miss the inheritance? child is subclass of parent class? – rt2800 Dec 25 '19 at 13:14
  • Since the parent class do not have public initialize method you can not call it from Parent class object. You need to have public method. Or you need to cast Parent objects to appropriate child class object and then call method on it. – Chetan Dec 25 '19 at 13:15
  • Why you can not have public Initialize method on Parent class? – Chetan Dec 25 '19 at 13:17
  • 1
    The parent needs `public virtual void Initialize` then the child's will be `public override void Initalize`. And as rt2800 said you need to inherit Parent in the child classes `public class Child1 : Parent` – Matt Dec 25 '19 at 13:20
  • Yep, sorry, I forgot the inheritence in my example. Fixed. – Deckweiss Dec 25 '19 at 13:45

3 Answers3

2

You should define your method as virtual in base class and then override in children classes.

  public class Child1 : Parent
{
    private int _value;
    public int Value => _value;

    public override void Initialize()
    {
        base.Initialize();
        _value = 1;
    }
}

public class Child2 : Parent
{
    private double _value;
    public double Value => _value;

    public override void Initialize()
    {
        base.Initialize();
        _value = 1.0;
    }
}

public class Parent
{
    private bool _initialized;
    private string _id;
    public string Id => _id;

    public virtual void Initialize()
    {
        if(!_initialized) 
        {
            _id = System.Guid.NewGuid().ToString();
        }
    }
}
Saeid Babaei
  • 481
  • 2
  • 16
2

First of all, you didn't inherit from anything, nor have you overriden any members.The Parent.Initialize isn't even virtual. You probably wanted

public class Parent
{
    protected virtual void Initialize() 
    {
       ... 
    } 
} 

public class Child1 : Parent
{
   public override void Initialize()
   {
       ... 
   } 
} 

public class Child2 : Parent
{
   public override void Initialize()
   {
       ... 
   } 
} 

Second of all, if you do that, you're gonna get an error saying you cannot change the accessibility of an inherited member in a child class. That would break encapsulation, as you could easily take any class with protected members, inherit from it and change all of the members to public (going other way around, from public to protected, would violate the LSP).

There's no need to declare the Parent.Initialize as protected; the only thing it'd give is that casting a child to Parent would render you unable to use the Initialize method. To utilize polymorphism the method needs to be public. If you want your Parent class to be just a template for derived classes that cannot be instantiated by itself, consider making it into an abstract class.

V0ldek
  • 9,623
  • 1
  • 26
  • 57
0

Initizalize method of base class declare with virtual or abstract keyword. See more Difference between virtual and abstract methods, https://www.tutorialride.com/csharp/virtual-methods-and-abstract-class-in-c-sharp.htm

Ramil Aliyev 007
  • 4,437
  • 2
  • 31
  • 47