使用实现的抽象类,操作委托参数不匹配

时间:2013-04-02 19:07:10

标签: c# oop delegates polymorphism

我有以下抽象类:

public abstract class BaseClass{
    public object contents { get; set; }
    public Action<BaseClass> mutator;
    public abstract void Initialise();
}

这将由多个类使用,这些类将覆盖Initialize方法以将值分配给contents,而mutator将使用mutator委托在特定点处进行变更。时间。

我有以下静态类,每个方法都打算用作public static class Mutators{ public static void VariantA(A inputObj){ // inputObj.contents = something else } public static void VariantB(A inputObj) { } // etc. etc. }

public class A : BaseClass{
    public A(){
        mutator = Mutators.VariantA;
    }

    public override void Initialise(){
        /* set the value of contents property here */
    }
}

然后我有了A类,它实现了BaseClass。我试图将Mutators.VariantA分配给mutator委托,但我无法。

A method or delegate

具体而言,我收到以下错误:System.Action<BaseClass>(BaseClass)' parameters (CS0123) Mutators.VariantA(A)'参数与委托Mutators.VariantA(A)不匹配

我理解A需要类型为BaseClass的对象,并且声明Action接受类型为A的输入,但是当BaseClass类实现{{}时1}}我以为我能做到这一点?

来自动态类型语言我很难掌握以这种方式处理类型:(

有没有什么方法可以用这种方式指向一个带抽象类型输入的函数?我是否需要查看其他一些设计模式?

由于

2 个答案:

答案 0 :(得分:4)

  

我理解Mutators.VariantA(A)需要一个A类型的对象,并且Action被声明为接受BaseClass类型的输入,但是当A类实现BaseClass时,我以为我能够做到这一点? / p>

绝对不是。

Action<BaseClass>必须能够接受任何 BaseClass对象。例如,如果您的代码有效,我可以写:

Action<BaseClass> mutator = Mutators.VariantA;
mutator.Invoke(new B());

(其中B是从BaseClass派生的另一个类。)

B派生自BaseClass的事实使其对调用有效 - 但它不会帮助您的VariantA方法正常运行。

为什么你在这里有一个mutator并不是很清楚 - 我强烈怀疑你应该从它的突变中抽象BaseClass。我仍然不遵循你想要实现的目标,但这种设计模式不会帮助你以类型安全的方式实现目标。

可以写:

public abstract class BaseClass<T> where T : BaseClass<T> {
    public object Contents { get; set; }
    public Action<T> Mutator { get; set; }
    public abstract void Initialise();
}

......然后:

public class A : BaseClass<A> {
    public A() {
        Mutator = Mutators.VariantA;
    }
}

......那时你会写一些可以改变“A”值的东西。但根据我的经验,这种通用嵌套变得非常混乱,非常快。

答案 1 :(得分:1)

我已经使用了您当前的示例,并将其中一个类的方法签名更改为以下内容并且可以正常工作

    public abstract class BaseClass
    {
        public object contents { get; set; }
        public Action<BaseClass> mutator;
        public abstract void Initialise();
    }
    public static class Mutators
    {
        public static void VariantA(BaseClass baseClass)
        {
            // inputObj.contents = something else
        }

        public static void VariantB(A inputObj) { } // etc. etc.
    }
    public class A : BaseClass
    {
        public A()
        {
            mutator = Mutators.VariantA;
        }

        public override void Initialise()
        {
            /* set the value of contents property here */
        }
    }