让我们首先将问题重写为可理解的东西.而不是X和H,我们称之为食物和动物.您的方案是:
abstract class Animal
{
protected Food favourite;
protected Animal(Food f) { this.favourite = f; }
}
abstract class Food
{
}
sealed class Banana : Food
{
public void Peel() {}
}
sealed class Monkey : Animal
{
public Monkey(Banana banana) : base(banana) {}
public PeelMyBanana()
{
this.favourite.Peel(); // Error, favourite is of type Food, not Banana
}
}
Run Code Online (Sandbox Code Playgroud)
你的问题是:
我如何永久地将"最爱"称为"猴子"中的"香蕉"类型?
简短的回答是:你做不到.该字段属于给定类型,可以包含对Food类型实例的任何引用.编译器和运行时不知道或不关心您碰巧知道对事实上将分配给该字段的事物类型的更强限制.
有很多方法可以解决这个问题.您可以添加一个为您进行转换的访问者:
sealed class Monkey : Animal
{
public Monkey(Banana banana) : base(banana) {}
private Banana Favourite { get { return (Banana)this.favourite; } }
public PeelMyBanana()
{
this.Favourite.Peel(); // Works
}
}
Run Code Online (Sandbox Code Playgroud)
或者您可以对基类进行泛化:
abstract class Animal<F> where F : Food
{
protected F favourite;
protected Animal(F f) { this.favourite = f; }
}
abstract class Food
{
}
sealed class Banana : Food
{
public void Peel() {}
}
sealed class Monkey : Animal<Banana>
{
public Monkey(Banana banana) : base(banana) {}
public PeelMyBanana()
{
this.favourite.Peel(); // Legal; Animal<Banana>.favourite is of type Banana
}
}
Run Code Online (Sandbox Code Playgroud)