首先是代码示例:
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
(反过来,从public
到protected
,将违反LSP(。
没有必要将Parent.Initialize
声明为protected
;它唯一会给出的是,将孩子投Parent
会使您无法使用Initialize
方法。要利用多态性,需要public
该方法。如果希望Parent
类只是无法自行实例化的派生类的模板,请考虑将其制作成abstract class
。
使用虚拟或抽象关键字初始化基类声明的方法。查看更多 虚拟方法和抽象方法之间的区别,https://www.tutorialride.com/csharp/virtual-methods-and-abstract-class-in-c-sharp.htm