已更新
好的,所以我正在玩类和继承,我正在尝试做一些我以前在一个源代码是C ++的游戏中做过的事情,我想知道这里有人能帮我理解我是怎么做的用C#。
我想做的是两件事:
首先当我创建某个类的对象时,我想将一个整数传递给构造函数,并使用该整数来确定将初始化哪个sublcass。
像这样:职业newVoc = new Vocation(1); 并且1将选择具有该VocationId的第一个sublcass或子类。第二件事,我已经拥有一个从Creature Class继承的玩家类,但我希望玩家类本身包含一个Vocation对象。所以我可以设置职业,当我进行属性更改并且播放器具有不同的属性时...这是一个示例代码,尝试使用我所说的内容,希望有人理解我的意思。
好的,我现在收到一个错误。无法隐式转换类型Mage' to
职业'
这就是我得到的......
Vocation.cs
using UnityEngine;
using System.Collections;
public enum VocationType { Mage, Warrior }
public class Vocation
{
}
public static class VocationFactory
{
public static Vocation CreateVocation(VocationType type)
{
switch (type)
{
case VocationType.Mage:
{
return new Mage();
break;
}
}
}
}
public class Mage
{
public string Name = "Mage";
public Mage()
{
}
}
Player.cs
using UnityEngine;
using System.Collections;
public class Player : Creature
{
public uint Level {get; set; }
public uint Dexterity {get; set; }
public uint Vitality {get; set; }
public uint Intelligence {get; set; }
public uint Strength {get; set; }
public ulong Experience {get; set;}
public Player()
{
var voc = VocationFactory.CreateVocation(VocationType.Mage);
Level = 1;
Health = 500;
MaxHealth = 100;
Mana = 50;
MaxMana = 100;
Experience = 0;
Dexterity = 0;
Vitality = 0;
Intelligence = 0;
Strength = 0;
}
}
答案 0 :(得分:5)
您不应该从基类创建对象。请改用工厂,也可以使用枚举来定义类型。
如果从Dmitry's answer on your previous question开始,可以创建一个实例化对象的工厂类。例如:
public enum VocationType { Mage, ... }
public static class VocationFactory
{
public static Vocation CreateVocation(VocationType type)
{
switch (type)
{
case VocationType.Mage:
{
return new Mage();
break;
}
}
throw new Exception($"You did not implement type '{type}'.");
}
}
然后这样称呼:
var voc = VocationFactory.CreateVocation(VocationType.Mage);
答案 1 :(得分:2)
我认为您不希望Vocation
成为Player
的子类型,而是Player
具有的内容。 Player
甚至可能有多个职业。这反映了您展示的代码。
这是不可能做到的,但有很多方法可以解决。
构造函数需要指定类型,并且您不能指定祖先,您必须指定要实例化的实际类型。因此,new Vocation(1)
将只创建一个Vocation
实例,而不是子类。
解决这个问题的方法是使用case
语句:
switch (vocation)
{
case 1:
return new Mage();
case 2:
return new Sorceror();
}
但这不是好设计,我不会这样做。在C#中你有枚举,所以至少要使用它们:
enum VocationType
{
Mage,
Sorceror
}
switch (vocation)
{
case Mage:
return new Mage();
case Sorceror:
return new Sorceror();
}
这仍然不好。这里的问题是你正在寻找的是一个创造性的模式,而不是一个编程技巧。
你真正想要的是一个工厂,它可以创造你想要的任何类型的玩家。
在c#中执行此操作的更好(可能仍然不是最佳)方法是具有工厂方法的泛型,您可以将实例Type
传递给实例化,如下所示:
public class PlayerFactory
{
public Player Create<V>()
where V : Vocation
{
Player p;
p = new Player();
p.SetVocation<V>();
return p;
}
}
SetVocation<V>()
方法应该是:
public class Player : Creature
{
private Vocation ChosenVocation;
public Player()
{
}
public void SetVocation<V>()
where V : Vocation
{
ChosenVocation = new V();
}
}
您现在可以按如下方式创建这些实例:
switch (vocation)
{
case Mage:
return PlayerFactory.Create<Mage>();
case Sorceror:
return PlayerFactory.Create<Sorceror>()
}
为什么这么大惊小怪?
您希望尽快从1
或Vocation.Mage
等代码中删除自己,并切换到实际类型(即实现的代码)。上述方法允许您通过以下方式轻松扩展代码:
Vocation
枚举; case
添加到switch()
; Sorceror
类)。答案 2 :(得分:0)
对于第二点,只需创建一个Vocation
和一个新var player = new Player { Vocation = VocationFactory.CreateVocation(VocationType.Mage) };
(根据Patrick的回答):
Vocation
这假设您在Player
- 类上有一个属性class Player : Create
{
public Vocation Vocation { get; set; }
}
:
{{1}}
答案 3 :(得分:0)
对于First
要求,您可以constructor
一个parameter
,并在构造函数的实现中调用您想要的类。
public class Class1
{
public Class1(int i)
{
// Your implementation logic goes here
}
}
以下是您的更新代码,我认为这些代码符合您的Second
要求。
public class Vocation
{
public Vocation()
{
}
public Vocation(int i)
{
}
}
public class Player : Creature
{
Vocation v;
public Player(int i)
{
}
public void SetVocation(int value)
{
// if you wanna set it to value
v = new Vocation(value);
}
}