[英]Is it incorrect to use classes (instead of interfaces) to set up plug-in mechanism?
假設這種假設情況:我有一個類的層次結構:
public class MyBase : System.Windows.Forms.TreeNode
{
public virtual void Init() {...}
}
現在,我希望允許第三方使用MyBase來開發其派生類,如下所示:
public class Drv1 : MyBase { public override void Init() {...} }
public class Drv2 : MyBase { public override void Init() {...} }
我希望我的應用程序能夠使用Drv1和Drv2作為插件。
現在,我的問題是:
使用類(而不是接口)來建立插件機制是不正確的(或不好的做法)?
難道我犯了一個錯誤,我沒有使用接口來提供第三締約方的接口 ? (因為我想說服其他人為我的應用開發插件)
如果問題2的答案是“是”,那么我該如何使用接口(因為MyBase是從TreeNode派生的)? (這個答案對我很關鍵)
提前謝謝了。
我使用以下規則:
如果base中需要任何代碼,請class
。
如果只需要結構,或者需要“繼承”多個class
,請使用interfaces
。
如果同時需要,則功能和多重繼承都需要使用。
這實際上取決於您稍后對這些類的處理方式。
在您的情況下,您應該使用基class
因為virtual
方法中包含一些代碼,並且您從屬於第三方的類繼承。
但是一旦您的業務類應該使用該類的不同實現,那么它值得添加接口並在IoC或其他方面使用它。
我認為僅出於它的目的而去接口是不正確的方法。
使用類(而不是接口)來建立插件機制是不正確的(或不好的做法)?
C#或.NET都沒有將其標記為錯誤的內容。 它們描述了您的代碼在什么情況下可以繼續工作,什么時候不起作用。 不好的做法是一種見解,但是兩種方法都有其優點和缺點。
如果問題2的答案是“是”,那么我該如何使用接口(因為MyBase是從TreeNode派生的)? (這個答案對我很關鍵)
如果您的調用者需要提供派生自TreeNode
的類型,並且您希望使用接口,則可以。
public interface IMyInterface {
void Init() {...}
}
您可以不需要實現IMyInterface
類從TreeNode
派生,但是您不需要:您可以確保將其公開給您自己的應用程序的唯一方法是通過通用注冊方法,其中通用類型約束確實將類型強制為兩種從TreeNode
派生並實現此接口:
public void RegisterTreeNode<T>() where T : TreeNode, IMyInterface {...}
如果插件能夠調用RegisterTreeNode<Drv1>()
,則可以確保在編譯時它將滿足您的要求。 您當然可以使用不同的方法簽名,可能是處理TreeNode
類的各個實例的方法簽名,這是類型約束在這里很關鍵。 如果來電者嘗試
class X : IMyInterface { public void Init() {...} }
接着
RegisterTreeNode<X>();
編譯器只會拒絕此操作。 該插件可能會創建此X
本身的實例,但是如果您的應用程序從未看到過它們,則它們不會造成任何傷害。
然后第三方可以執行以下操作:
public class Drv1 : TreeNode, IMyInterface { ... }
public class Drv2 : TreeNode, IMyInterface { ... }
甚至
public class Drv3 : SuperTreeNode, IMyInterface { ... }
其中SuperTreeNode
是從標准TreeNode
派生的。
這可能是在此處使用接口的主要好處:它與現有類兼容,這些類在標准TreeNode
之上提供了附加功能。
這有兩種方式:在這里使用通用基類而不是接口的主要好處是您自己的代碼可以提供其他功能。
PS:根據您要執行的操作,也可以將其解耦,以使您的基類/接口負責創建 TreeNode
對象,而不是從TreeNode
派生。 支持這種方法的一般規則稱為“組成而不是繼承”,值得一讀。 它可能適合您的特定用例,也可能不合適。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.