【问题标题】:How do I stop casting in this scenario?在这种情况下如何停止投射?
【发布时间】:2012-01-24 18:00:48
【问题描述】:

我有以下操作:

abstract class AAction
{}

class BlueAction: AAction
{
    void Foo1(){// do stuff}
    void Foo2(){// do stuff}
}

以及应该包含动作的插件:

class APlugin
{
    AAction _action;

    APlugin(AAction action)
    {
        _action = action;
    }

}

class BluePlugin: APlugin
{
    BluePlugin(): base(new BlueAction());
    {
    }

    voif Foo()
    {
        // do stuff with BlueAction's methods
        ((BlueAction)_action).Foo1();
        ((BlueAction)_action).Foo2();
    }
}

我正在尝试将此设计与设计模式相匹配,但没有成功。

我只想强制APlugin 的派生类拥有AAction

我可以这样做:

BlueAction act = (BlueAction)_action;
act.Foo1();
act.Foo2();

使用泛型(如建议的那样)不允许我拥有我真正需要的 APlugins 列表。

但这对我来说是不行的。有什么想法吗?

【问题讨论】:

  • 我想也许你希望Foo1Foo2 成为基类的抽象成员?那么您的呼叫站点将不需要投射,_action.Foo1();
  • 代码class BlueAction: AAction { void Foo1(); void Foo2(); }没有编译.....
  • @asawyer 不,我希望 BlueAction 有自己的方法
  • @RoyiNamir 该代码仅用于演示,它不是从我的项目中复制的。我的问题是关于设计而不是发现错误:)

标签: c# design-patterns inheritance


【解决方案1】:

只保留 BlueAction 实例:

class APlugin
{
    AAction _action;

    APlugin(AAction action)
    {
        _action = action;
    }
}

class BluePlugin: APlugin
{
    BlueAction _blueAction = new BlueAction();

    BluePlugin(): base(_blueAction) 
    { 
    }

    void Foo()
    {
        // do stuff with BlueAction's methods
        _blueAction.Foo1();
        _blueAction .Foo2();
    }
}

【讨论】:

  • _action 和 _blue action 应该是一个。如果我将属性设置为操作,则它不会在 _blueAction 实例中。你说的是糟糕的设计。
  • 不,不是。它们是同一个对象,你只有两个引用。但是是同一个例子。这与您在示例中显示的相同,但将引用保留在字段中。我猜你在说它们不一样之前没有尝试过,这是一个糟糕的设计......
  • 实际上我没有注意到 BlueAction 构造函数中的参数...:p 我喜欢你的方法。我不喜欢有两个实例,它们可能会混淆未来的开发人员
  • 您不会有两个实例,只会有一个!如果您未来的开发人员可能对此感到困惑,那么您需要更好的开发人员。这是c#的基础。
  • 我只关心开发人员不必在类中添加 blueAction 字段这一事实。他们可能会将其传递到基地并从该点继续施法。
【解决方案2】:

假设你希望构造函数保持不变,你可以这样做:

class APlugin
{
    public AAction Action { get; private set; }

    APlugin(AAction action)
    {
        Action = action;
    }

}

class BluePlugin: APlugin
{
    private ActualAction
    {
        get { return Action as BlueAction; }
    }

    BluePlugin(): base(new BlueAction());
    {
    }

    void Foo()
    {
        // do stuff with BlueAction's methods
        ActualAction.Foo1();
        ActualAction.Foo2();
    }
}

【讨论】:

    【解决方案3】:

    使用泛型:

    class APlugin<TAction> where TAction : AAction
    {
        TAction _action;
    
        APlugin(TAction action)
        {
            _action = action;
        }
    
    }
    
    class BluePlugin: APlugin<BlueAction>
    {
        BluePlugin(): base(new BlueAction());
        {
        }
    
        void Foo()
        {
            // do stuff with BlueAction's methods
            _action.Foo1();
            _action.Foo2();
        }
    }
    

    【讨论】:

    • 代码class BlueAction: AAction { void Foo1(); void Foo2(); } 没有编译——他不能在类中有非抽象方法或没有主体的函数......这个问题不明白
    • 我假设 Foo1 和 Foo2 有主体,但为了清楚起见,它们只是被省略了。
    • 忘了说我想要一个APlugins列表!!!我真的很抱歉!否则你的解决方案很棒
    • 我之前评论的解决方案:stackoverflow.com/questions/353126/… :p 我相信我的问题现在已经解决了!
    • 对另一个问题的回答可能与您能够做到这一点一样接近。它仍然受到限制,因为您的列表不仅限于包含 APlugin 实例,还包含新的虚拟基类。完全在您的控制之下可能没什么大不了的,并且可能没有虚拟基类的其他实现,但仍然是一个限制。此外,那个虚拟基类应该是一个接口。你不会有任何实现的意图(大概)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多