我有以下抽象类:
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}}我以为我能做到这一点?
来自动态类型语言我很难掌握以这种方式处理类型:(
有没有什么方法可以用这种方式指向一个带抽象类型输入的函数?我是否需要查看其他一些设计模式?
由于
答案 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 */
}
}