棘手的 Inheritance-Related 架构
Tricky Inheritance-Related Architecture
我正在尝试用 C# 为视频游戏中的不同角色类型设计一个系统。我的角色类型有一个简单的继承树,它有一个 Humanoid
基础 class,它有几个派生的 class,例如 Human
、Alien
等。每个这些字符类型包括 body 几个部分。目前这些部分存储在 Body
class 的实例中,每个部分由 BodyPart
class.
的实例描述
当我想为 BodyPart
派生 classes 时,主要的复杂性就来了,因为每个字符类型的 body 部分都会有一些额外的特定属性。我希望将 BodyPart
实例分组到 Body
class 的主要原因是我可以使用索引器,因为我需要能够迭代它们并且仍然能够使用点符号可以轻松访问特定部分。
以下伪代码应该让您了解我正在努力实现的目标以及我已经尝试实现它的方式。
public class BodyPart
{
public float health;
//...
}
public class HumanBodyPart : BodyPart
{
public float exampleHumanStuff;
//.. human specific stuff
}
public class AlienBodyPart : BodyPart
{
public float exampleAlienStuff;
//.. alien specific stuff
}
public class Humanoid
{
public class Body<T> where T : BodyPart
{
public T head;
public T leftArm;
public T rightArm;
//...
public T this[int i]
{
get
{
switch (i)
{
case 0:
return head;
case 1:
return leftArm;
//...
}
}
}
}
public virtual Body<BodyPart> body { get; }
public void Example {
body.head.health = 50;
body[2].health = 55;
}
}
public class Human : Humanoid
{
public Body<HumanBodyPart> humanBody;
public override Body<BodyPart> body { get { return (Body<BodyPart>)humanBody; } }
public void Example
{
body.rightArm.exampleHumanStuff = 5;
}
}
public class Alien : Humanoid
{
public Body<AlienBodyPart> alienBody;
public override Body<BodyPart> body { get { return (Body<BodyPart>)alienBody; } }
public void Example
{
body.leftArm.exampleAlienStuff = 5;
}
}
这种方法的死胡同是 Body
class 不是逆变的(我认为?)所以将 Body<HumanBodyPart>
转换为 Body<BodyPart>
是行不通的.但是我想不出另一种方法来从基础 Humanoid
class 访问 Human
中的 Body<HumanBodyPart>
class 实例,以便在基础 class 它被视为 Body<BodyPart>
。有更好的方法吗?
您可以使 Humanoid
成为 BodyPart
本身的泛型:
public class Humanoid<T> where T : BodyPart
{
public class Body
{
public T head;
//...
public T this[int i]
{
get
{
switch (i)
{
case 0:
return head;
//...
}
return default;
}
}
}
public Body body { get; }
public void Example()
{
body.head.health = 50;
body [2].health = 55;
}
}
public class Human : Humanoid<HumanBodyPart>
{
public void Example()
{
body.rightArm.exampleHumanStuff = 5;
}
}
public class Alien : Humanoid<AlienBodyPart>
{
public void Example()
{
body.leftArm.exampleAlienStuff = 5;
}
}
此外,此 class 层次结构不支持所有可能的用例(例如不同 Humanoid
的集合,但您可以使用非通用接口解决一些问题(对于 Humanoid
和 Body
)).
至于方差,它仅支持 C# 中的 interfaces and delegates(和数组,但不要使用它)。在你的情况下,这样的事情会起作用:
public interface IBody<out TInner>
{
public TInner head { get; }
public TInner leftArm { get; }
public TInner this[int i] { get; }
}
IBody<HumanBodyPart> humanBody = ...;
IBody<BodyPart> body = humanBody;
我假设您要分配 Humanoid 的特定 BodyPart class。我会用这个:
public class Humanoid <T> where T : BodyPart
{
public class Body<T>
{....
最后,当你描述一个人时,你可以使用:
public class Human : Humanoid <HumanBodyPart>
{.......
我正在尝试用 C# 为视频游戏中的不同角色类型设计一个系统。我的角色类型有一个简单的继承树,它有一个 Humanoid
基础 class,它有几个派生的 class,例如 Human
、Alien
等。每个这些字符类型包括 body 几个部分。目前这些部分存储在 Body
class 的实例中,每个部分由 BodyPart
class.
当我想为 BodyPart
派生 classes 时,主要的复杂性就来了,因为每个字符类型的 body 部分都会有一些额外的特定属性。我希望将 BodyPart
实例分组到 Body
class 的主要原因是我可以使用索引器,因为我需要能够迭代它们并且仍然能够使用点符号可以轻松访问特定部分。
以下伪代码应该让您了解我正在努力实现的目标以及我已经尝试实现它的方式。
public class BodyPart
{
public float health;
//...
}
public class HumanBodyPart : BodyPart
{
public float exampleHumanStuff;
//.. human specific stuff
}
public class AlienBodyPart : BodyPart
{
public float exampleAlienStuff;
//.. alien specific stuff
}
public class Humanoid
{
public class Body<T> where T : BodyPart
{
public T head;
public T leftArm;
public T rightArm;
//...
public T this[int i]
{
get
{
switch (i)
{
case 0:
return head;
case 1:
return leftArm;
//...
}
}
}
}
public virtual Body<BodyPart> body { get; }
public void Example {
body.head.health = 50;
body[2].health = 55;
}
}
public class Human : Humanoid
{
public Body<HumanBodyPart> humanBody;
public override Body<BodyPart> body { get { return (Body<BodyPart>)humanBody; } }
public void Example
{
body.rightArm.exampleHumanStuff = 5;
}
}
public class Alien : Humanoid
{
public Body<AlienBodyPart> alienBody;
public override Body<BodyPart> body { get { return (Body<BodyPart>)alienBody; } }
public void Example
{
body.leftArm.exampleAlienStuff = 5;
}
}
这种方法的死胡同是 Body
class 不是逆变的(我认为?)所以将 Body<HumanBodyPart>
转换为 Body<BodyPart>
是行不通的.但是我想不出另一种方法来从基础 Humanoid
class 访问 Human
中的 Body<HumanBodyPart>
class 实例,以便在基础 class 它被视为 Body<BodyPart>
。有更好的方法吗?
您可以使 Humanoid
成为 BodyPart
本身的泛型:
public class Humanoid<T> where T : BodyPart
{
public class Body
{
public T head;
//...
public T this[int i]
{
get
{
switch (i)
{
case 0:
return head;
//...
}
return default;
}
}
}
public Body body { get; }
public void Example()
{
body.head.health = 50;
body [2].health = 55;
}
}
public class Human : Humanoid<HumanBodyPart>
{
public void Example()
{
body.rightArm.exampleHumanStuff = 5;
}
}
public class Alien : Humanoid<AlienBodyPart>
{
public void Example()
{
body.leftArm.exampleAlienStuff = 5;
}
}
此外,此 class 层次结构不支持所有可能的用例(例如不同 Humanoid
的集合,但您可以使用非通用接口解决一些问题(对于 Humanoid
和 Body
)).
至于方差,它仅支持 C# 中的 interfaces and delegates(和数组,但不要使用它)。在你的情况下,这样的事情会起作用:
public interface IBody<out TInner>
{
public TInner head { get; }
public TInner leftArm { get; }
public TInner this[int i] { get; }
}
IBody<HumanBodyPart> humanBody = ...;
IBody<BodyPart> body = humanBody;
我假设您要分配 Humanoid 的特定 BodyPart class。我会用这个:
public class Humanoid <T> where T : BodyPart
{
public class Body<T>
{....
最后,当你描述一个人时,你可以使用:
public class Human : Humanoid <HumanBodyPart>
{.......