【发布时间】:2017-12-04 05:46:15
【问题描述】:
下面的设计只是一个展示我的问题的模板。
public interface IHero
{
string Name { get; }
int Level { get; }
}
public interface IWarlock : IHero
{
string MagicType { get; }
}
public interface IKnight : IHero
{
string CommandHierarchy { get; }
}
public class Warlock : IWarlock, IHero
{
string IWarlock.MagicType { get { throw new NotImplementedException(); } }
string IHero.Name { get { throw new NotImplementedException(); } }
int IHero.Level { get { throw new NotImplementedException(); } }
public Warlock(string name, int level, string magicType)
{
}
}
public class Knight : IKnight, IHero
{
string IKnight.CommandHierarchy { get { throw new NotImplementedException(); } }
string IHero.Name { get { throw new NotImplementedException(); } }
int IHero.Level { get { throw new NotImplementedException(); } }
public Knight(string name, int level, string commandHierarchy)
{
}
}
public class NullHero : IHero
{
public string Name { get { return string.Empty } }
public int Level { get { return -1; } }
}
class Program
{
static void Main(string[] args)
{
}
//Increments the hero's level.
static IHero LevelUp(IHero hero)
{
if (hero is IWarlock)
return new Warlock(hero.Name, hero.Level + 1, (hero as IWarlock).MagicType);
else if (hero is IKnight)
return new Knight(hero.Name, hero.Level + 1, (hero as IKnight).CommandHierarchy);
else
return new NullHero();
}
}
问题是下次我添加一个新英雄时,我必须在 LevelUp 函数中添加另一个 if 语句,这会变得混乱。
我知道我可以使用 Activator.CreateInstance 创建一个新实例,但是有两个问题,1.所有对象都是不可变的。 2.构造函数中参数的数量和类型。
有人可以提出解决这个问题的方法吗?
编辑: 是的,cmets 部分的每个人都是正确的。我可以在 IHero 界面中添加 LevelUp 作为定义。
也许我选择了错误的概念来表达我的问题,但假设我想在外部处理 LevelUp,如模板中所示。有没有办法解决我唯一的问题,即创建一个 IHero 类型的新实例而无需进行类型检查?
【问题讨论】:
-
为什么不在IHero中定义LevelUp?任何实现都会简单地返回
this(当然我会质疑你是否真的需要在那里返回任何东西)。 -
我认为您应该有一个实现 IHero 的类,并且您的两个英雄都应该继承该类。现在,您将重新定义每种新的子英雄类型中的英雄。但是它们都具有相同的属性(名称和级别),因此 iguess 将执行相同的操作。而且你的升级功能看起来很奇怪,因为你给了整个英雄并且它返回了一个英雄。在 IHero 中创建一个类似“LevelUp()”的方法,然后从那里开始。
-
@pijemcolu 是的,在这种情况下我可以。因为在 IHero 中将 LevelUp 作为定义是有意义的。但就像我说的,这只是一个简单的模板。我的业务逻辑要复杂得多(我无法透露),但问题是一样的。也许我所要求的不可行,但我需要与社区确认。
-
一切皆有可能,但要付出理智的代价。你看过泛型吗? msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx 。你的 LevelUp 看起来像
static T LevelUp<T>(T hero) where T : IHero { ... hero.Level++; ...} -
@pijemcolu 您的建议与我在模板中显示的没有什么不同。我本可以简单地完成 Level++,但我喜欢保持我的对象不可变,因此 Level++ 不会工作。它们只能通过返回对象的新实例来修改。
标签: c# .net reflection interface solid-principles