【问题标题】:What is the proper way to call a child function on an array of parent在父数组上调用子函数的正确方法是什么
【发布时间】:2020-04-16 02:57:45
【问题描述】:

代码示例先:

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();
        }
    }
}

我想做什么:

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);    
        }
    }
}

但是这段代码不起作用,因为它试图调用受保护的初始化而不是子类初始化。正如我在this question 中所读到的,您不能将对象从父类转换为其子类。

我觉得从逻辑上讲,这种构造是有道理的,因为父类可以容纳所有公共字段和逻辑,而子类则有差异,并在自己的初始化方法中做不同的事情。 我想在数组中轻松处理混合的一堆子类并调用它们的初始化函数。并且永远不应该存在自己初始化的父类。

我是不是在做一些根本性的错误,这种构造是否有不同的方法,可以让我调用一堆不同子类的初始化方法?

我非常感谢一个工作代码示例。

【问题讨论】:

  • 你错过了继承吗? child 是父类的子类?
  • 由于父类没有公共的初始化方法,你不能从父类对象中调用它。你需要有公共方法。或者您需要将 Parent 对象转换为适当的子类对象,然后对其调用方法。
  • 为什么Parent类不能有public Initialize方法?
  • 父母需要public virtual void Initialize,然后孩子需要public override void Initalize。正如 rt2800 所说,您需要在子类中继承 Parent public class Child1 : Parent
  • 是的,抱歉,我忘记了示例中的继承。固定。

标签: c# oop


【解决方案1】:

您应该在基类中将您的方法定义为虚拟方法,然后在子类中覆盖。

  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();
        }
    }
}

【讨论】:

    【解决方案2】:

    首先,你没有从任何东西继承,也没有覆盖任何成员。Parent.Initialize 甚至不是virtual。你可能想要

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

    其次,如果你这样做,你会得到一个错误,说you cannot change the accessibility of an inherited member in a child class。这会破坏封装,因为您可以轻松地获取具有protected 成员的任何类,从中继承并将所有成员更改为public(反过来,从publicprotected,将违反@ 987654322@)。

    无需将Parent.Initialize 声明为protected;它唯一会给出的是将孩子强制转换为Parent 会使您无法使用Initialize 方法。要利用多态性,方法需要是public。如果您希望您的Parent 类只是无法自行实例化的派生类的模板,请考虑将其制成abstract class

    【讨论】:

      【解决方案3】:

      【讨论】:

        猜你喜欢
        • 2020-08-21
        • 1970-01-01
        • 1970-01-01
        • 2019-10-19
        • 1970-01-01
        • 1970-01-01
        • 2015-11-30
        • 2012-06-18
        • 1970-01-01
        相关资源
        最近更新 更多