Ter*_*al8 6 c# inheritance interface
我想我会在我的代码中使用一些案例研究作为我的意思的一个例子.
现在,我正在为基于组件的游戏系统开发一个行为/动作系统.GameObjects可以附加一个IBehaviorComponent和一个IActionComponent,只显示相关细节,公开以下内容:
public interface IBehaviorComponent : IBaseComponent
{
IBehavior Behavior { get; }
}
public interface IActionComponent : IBaseComponent
{
IAction Action { get; }
void ExecuteAction(IGameObject target = null);
}
Run Code Online (Sandbox Code Playgroud)
现在,到目前为止这一切都很好(至少对我而言!).但是,当我查看IActionComponent的实现时,麻烦开始酿造.
例如,一个简单的IActionComponent实现:
public class SimpleActionComponent : IActionComponent
{
public IAction Action { get; protected set; }
public void ExecuteAction(IGameObject target = null)
{
Action.Execute(target);
}
public void Update(float deltaTime) { } //from IBaseComponent
}
Run Code Online (Sandbox Code Playgroud)
但是,假设我想引入一个更复杂的IActionComponent实现,它允许在定时计划上执行操作:
public class TimedActionComponent : IActionComponent
{
public IAction Action { get; protected set; }
public float IdleTime { get; set; }
public float IdleTimeRemaining { get; protected set; }
public void ExecuteAction(IGameObject target = null)
{
IdleTimeRemaining = IdleTime;
}
public void Update(float deltaTime)
{
if (IdleTimeRemaining > 0f)
{
IdleTimeRemaining -= deltaTime;
}
else
{
Action.Execute(target);
}
}
}
Run Code Online (Sandbox Code Playgroud)
而现在,假设我想公开IdleTime,以便可以通过外部影响来改变它.我最初的想法是创建一个新界面:
public interface ITimedActionComponent : IActionComponent
{
float IdleTime { get; set; }
float IdleTimeRemaining { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
但是,这里的问题是我的组件系统将所有内容存储在IBaseComponent的一级.因此,GameObject的动作组件将被检索为IActionComponent,例如,ITimedActionComponent,或IRandomizedActionComponent,甚至是ICrashTheProgramActionComponent.我希望其中的原因是显而易见的,因为我希望能够查询GameObject中的一个组件,而不必知道除了组件的基本类型(IActionComponent,IRenderableComponent,IPhysicsComponent等)之外它究竟需要什么.
有没有更清晰的方法来处理这个,这将允许我公开子类中定义的这些属性,而不必将检索到的IActionComponent转换为它感兴趣的类型?或者这只是实现这一目标的唯一/最佳方式.就像是:
public void IWantYouToAttackSuperSlow(IGameObject target)
{
//Let's get the action component for the gameobject and test if it's an ITimedActionComponent...
ITimedActionComponent actionComponent = target.GetComponent<IActionComponent>() as ITimedActionComponent;
if (actionComponent != null) //We're okay!
{
actionComponent.IdleTime = int.MaxValue; //Mwhaha
}
}
Run Code Online (Sandbox Code Playgroud)
现在我认为这是唯一的方式,但我想我会看到是否有一种模式隐藏在我不知道的木制品中,或者是否有人可以建议一种更好的方法来实现这一点.
谢谢!
你是对的,通过转换为子类型来测试特定的实现并不是一个好主意。从您提供的示例来看,您似乎想要对其IGameObject执行某些操作。与其IActionComponent公开一个以 为参数的方法,不如IGameObject以相反的方式进行操作,即让 采取IGameObject一个或多个(如果您愿意)可以执行的操作。
interface IActionComponent
{
ExecuteAction();
}
interface IGameObject
{
IActionComponent ActionComponent { get; }
}
Run Code Online (Sandbox Code Playgroud)
然后在执行方法中做
public void IWantYouToAttackSuperSlow(IGameObject target)
{
target.ActionComponent.ExecuteAction();
}
Run Code Online (Sandbox Code Playgroud)
根据您实现 IActionComponent 的方式,多态性将确保执行正确的代码。
有一种称为命令模式的模式似乎适合您的需要。