在父数组上调用子函数的正确方法是什么



首先是代码示例:

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

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

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

我是否做错了什么根本性的事情,是否有一种不同的方法来构建这种结构,让我调用一堆不同子类的初始化方法?

我真的很感激一个工作代码示例。

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

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

首先,你没有继承任何东西,也没有覆盖任何成员。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()
{
... 
} 
} 

其次,如果这样做,您将收到一个错误,指出您无法更改子类中继承成员的可访问性。这将破坏封装,因为您可以轻松地获取任何具有protected成员的类,从中继承并将所有成员更改为public(反过来,从publicprotected,将违反LSP(。

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

使用虚拟或抽象关键字初始化基类声明的方法。查看更多 虚拟方法和抽象方法之间的区别,https://www.tutorialride.com/csharp/virtual-methods-and-abstract-class-in-c-sharp.htm

相关内容

最新更新