我有一个很好的完整课程,这是令人敬畏的事情。我需要允许用户通过替换其中的某些方法来使用此类,但不允许继承,因为此类也用于其他应用程序类。
就像你有一个创建表的类,但是你需要允许用户重新定义创建表格单元格的方法,让用户在这个单元格中打印自定义的东西。但是,该类具有打印单元格内容的默认方式(如果用户不需要自定义它)。
是否有任何常用或标准化的方法来实现这一目标?
答案 0 :(得分:4)
有花生画廊"指出我的方法(在底部)不适合该法案,这是另一种方式:
使用委托。使用Action或Func类型定义某些公共属性。如果需要在代码中调用这些行为,请将属性与null进行比较。如果为null,请使用默认行为。如果没有,请调用值。
您的主叫代码可以设置属性,但不必。
您正在描述扩展方法,或者如果可用,则使用继承。
扩展方法可让您添加"现有类型的方法,无需创建新的派生类型,重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但它们被称为扩展类型的实例方法。对于用C#和Visual Basic编写的客户端代码,调用扩展方法和实际在类型中定义的方法之间没有明显区别。
https://msdn.microsoft.com/en-us//library/bb383977.aspx
继承与封装和多态性一起,是面向对象编程的三个主要特征(或支柱)之一。继承使您可以创建重用,扩展和修改其他类中定义的行为的新类。其成员被继承的类称为基类,而继承这些成员的类称为派生类。派生类只能有一个直接基类。但是,继承是可传递的。如果ClassC派生自ClassB,而ClassB派生自ClassA,则ClassC继承ClassB和ClassA中声明的成员。
https://msdn.microsoft.com/en-us/library/ms173149.aspx
您无法从所有.NET类型派生,但您可以为它们编写扩展方法。
答案 1 :(得分:1)
假设您可以修改现有类,则应将方法标记为虚拟。
这将允许您提供默认实现(这是您现有代码将使用的实现),并且能够在需要时使用自定义实现覆盖它。
您的基类可能类似于:
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
}
}
您现有的代码可以正常使用,您可以在需要的地方使用其他类。
答案 2 :(得分:-1)
我终于以这个解决方案结束了。它是由@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#";
}
}
在这个例子中,我使用的是使用Func委托扩展的MyTable类。这样我就可以允许我的软件模块的用户只扩展一个方法而不会弄乱其他类和对象。