我有一个很好的完整的类,这是做可怕的事情。我需要允许用户通过替换其中的一些方法来使用这个类,但是不允许继承,因为这个类也在其他应用程序类中使用。
这就像你有一个创建表格的类,但是你需要允许用户重新定义创建表格单元格的方法,让用户在这个单元格中打印一些自定义的东西。然而,这个类有一个默认的方式来打印单元格内容(以防用户不需要自定义它)。
是否有通用的或标准化的方法来实现这一点?
已更新
吃了"花生画廊";指出我的方法(在底部)不符合要求,这里有另一种方法:
使用代表团。定义某些类型为Action或Func的公共属性。在代码中需要调用这些行为的地方,将属性与null进行比较。如果为空,则使用默认行为。如果没有,调用这些值。
你的调用代码可以设置属性,但不是必须的。
(第一次尝试)替代方法:
您正在描述一个扩展方法,或者如果可用的话,可以使用继承。
https://msdn.microsoft.com/en-us//library/bb383977.aspx扩展方法使您能够"添加";方法转换为现有类型,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法是一种特殊类型的静态方法,但是调用它们时就好像它们是扩展类型上的实例方法一样。对于用c#和Visual Basic编写的客户端代码,调用扩展方法和在类型中实际定义的方法之间没有明显的区别。
继承、封装和多态性是面向对象编程的三个主要特征(或支柱)之一。继承使您能够创建重用、扩展和修改在其他类中定义的行为的新类。继承其成员的类称为基类,继承这些成员的类称为派生类。派生类只能有一个直接基类。然而,继承是可传递的。如果ClassC从ClassB派生,而ClassB从ClassA派生,则ClassC继承在ClassB和ClassA中声明的成员。https://msdn.microsoft.com/en-us/library/ms173149.aspx
你不能从所有的。net类型中派生,但是你可以为它们编写扩展方法。
假设您能够修改现有的类,您应该将您的方法标记为virtual。
这将允许您提供默认实现(这是您现有代码将使用的),并能够在需要的地方使用自定义实现来覆盖它。
你的基类可以是这样的:
public class TableMaker
{
public virtual string MakeTable()
{
//Provide default implementation used by existing code here
}
}
你的继承类可以重写虚方法:
public class SpecialTableMaker : TableMaker
{
public override string MakeTable()
{
//Provide specific implementation for cell text here
}
}
您现有的代码将正常工作,您可以在需要的地方使用其他类
我终于结束了这个解决方案。它是由@codenoir提出的,但是我也有一个演示整个机制的代码。
public class MyTable
{
public delegate string OnInsertHandler();
public event OnInsertHandler OnInsert;
public string Show()
{
string res = "-BEGIN-";
if (OnInsert != null) {
res += OnInsert ();
} else {
res += "#default insert#";
}
res += "-END-";
return res;
}
}
public class DelegateTester
{
public void OnTest()
{
MyTable mt = new MyTable();
Debug.Log("Default output: " + mt.Show()); // Shows "-BEGIN-#default insert#-END-"
// Changing functionality via delegate
mt.OnInsert += MyCustomInsert;
Debug.Log("Customized output: " + mt.Show()); // Shows "-BEGIN-#custom insert#-END-"
// Remove delegate
mt.OnInsert -= MyCustomInsert;
Debug.Log("Rollbacked output: " + mt.Show()); // Shows "-BEGIN-#default insert#-END-"
}
public string MyCustomInsert()
{
return "#custom insert#";
}
}
在这个例子中,我使用MyTable类,它是使用Func委托扩展的。这样,我可以允许我的软件模块的用户只扩展一个方法,而不会与其他类和对象混淆。