2012-03-26 106 views
1

我在我的一個應用程序中有幾個控件,它們都顯然擴展了Control類。爲界面強制執行某種類別類型?

我需要其中幾個具有一些共享接口,所以我創建了一個涵蓋共享功能的接口。

有什麼辦法可以強制我的接口只能被賦予Control的子類嗎?

即(僞)

interface IEmbed 

class MyControl1 : Control, IEmbed 

class MyControl2 : Control, IEmbed 

class MyClass : IEmbed 

我非常希望編譯器在這裏失敗,因爲MyClass的努力來實現IEmbed即使它不是控制。

我是否有過這種錯誤的方式,或者有沒有辦法強制這種行爲?

編輯

我一直在問我爲什麼要實施這種行爲。

我有一個方法,我想採取任何IEmbed實現並將其作爲子控件添加到另一個元素。

這一切都很好,但Controls.Add()拒絕帶一個IEmbed對象,並且這不能編譯。

我想如果我告訴編譯器,任何實現IEmbed的東西都必須是一個控件,它可能工作?

+0

爲什麼要將接口只給予Control的子類?也許你需要將它轉換回Control?如果是這樣,只需在調用實例'Control GetControl()'的接口中添加一個方法即使它不是Control的子類,它也必須提供關聯的Control,並且可以避免轉換... – digEmAll 2012-03-26 08:22:52

+0

請參閱編輯。 – KingCronus 2012-03-26 09:00:05

+0

@digEmAll如果OP意圖將所有實現都作爲Controls,那麼他確實需要子類化Control(請參閱Strillo的答案)。我認爲一個接口更好,因爲它沒有將任何東西綁定到一個特定的GUI框架,但是其中的一個「Control GetControl()」方法打破了這一切。 – 2012-03-26 09:06:58

回答

6

不,在編譯時無法強制執行此操作。

可以通過如果obj is Control使用obj作爲IEmbed實例之前,有你的框架代碼測試在運行時執行它。

更新:基於從意見反饋,它看起來像一個很好的解決辦法是從中間abstract class EmbedControl : Control繼承,使您的方法接受一個EmbedControl而不是IEmbed(在這種情況下,不會真的是需要保持界面,因爲你可以簡單地在基類中使用abstract方法)。

儘管上述方法可以很好地工作,但在某些情況下,強迫「客戶」類的實現者從您自己的中間類派生出來是不可取的,即使您需要它們從「基」類Control派生同時。在這種情況下,另一個好辦法是使用泛型:

public void DoSomethingWithControl<T>(T control) where T : Control, IEmbed 
+0

我同意,問題是,我們不知道爲什麼OP需要強制執行此行爲,並且可能還有另一種方法來實現這一點... – digEmAll 2012-03-26 08:28:56

+0

我想我會重新考慮我的設計... – KingCronus 2012-03-26 08:52:52

+0

我有一個方法,我想要採取任何IEmbed實現並將其作爲子控件添加到另一個元素。 這一切都很好,但Controls.Add()拒絕採用IEmbed對象,並且這不會編譯。 我想如果我告訴編譯器,實現IEmbed的東西必須是一個控件,它可能會工作? – KingCronus 2012-03-26 09:00:12

2

我不認爲有一種方法來執行這樣的事情 - 但我不認爲你真的需要,你纔可以檢查在運行時如果你的接口的實例是一個Control。

但是:alternativley只使用一個抽象類(從Control派生的),而不是接口:

abstract class EmbedControl 
    : Control 
{ 
    // your abstract members 
} 

class MyControl1 : EmbedControl 
5

如果你需要做的進行這樣的檢查,那麼我建議你檢查你的設計。一個接口只是一個契約,並不會限制遵守它的東西。如果類型很重要,那麼你應該嘗試一種不同的方法,比如基類。 如何使用抽象類(可以指定類型約束)需要繼承者來實現接口的方法?

interface IInterface 
{ 
    void Method1(); 
    int Property1 { get; } 
} 

abstract class BaseClass: Control, IInterface 
{ 
    public abstract void Method1(); 
    public abstract int Property1 { get; } 
} 

這隻會確保從BaseClass派生的任何類都是一個Control並實現IInterface。

0

什麼不使用聲明和檢查T是一個控制?

此外,我同意什麼是寫的abaove,爲什麼要一個接口是一種類型?它似乎是一個糟糕的deszign,你知道你將把你的接口重新投入到控件後...

0

其實我無法想象爲什麼你需要那個,但控制是IComponent的後代。 也許你應該從那裏繼承?

0

那麼,我提供的解決方案是一個非常醜陋的,但它在編譯時失敗。

public interface IEmbed<T> where T: Control 
{ 
} 

public class A :Control, IEmbed<A> 
{ 
} 

//this fails at compile time as B does not inherit from Control class. 
public class B : IEmbed<B> 
{ 
} 
+0

我的意思是它失敗,因爲B沒有實現控制。這是所問的行爲。 – daryal 2012-03-26 08:48:48

+0

thx這是星期一,錯過了代碼中的評論。我認爲代碼一般不會編譯。 – RvdK 2012-03-26 08:55:35

+2

這不是一個好的解決方案。開發人員可能很容易打破這個不知道「T」的目的,並聲明「C類:IEmbed 」。 – 2012-03-26 09:11:10