2012-02-26 21 views
3

我正在寫一個虛擬/抽象程序,我希望被覆蓋。但是,它們也可能不會被覆蓋,這也很好。問題是找出這些程序中的一個是否被實際覆蓋。如果他們沒有被覆蓋,我不應該試圖調用這些程序,而是需要改變一些不同的東西。如果我嘗試打電話給他們其中一個並且沒有被覆蓋,我得到Abstract Error如何確保未來的繼承覆蓋過程?

有沒有一種方法可以檢測這些程序是否被覆蓋?

這裏是他們是如何宣稱樣本:

type 
    TMyClass = class(TObject) 
    protected 
    procedure VProc; virtual; 
    procedure VAProc; virtual; abstract; 
    end; 
+0

我覺得你的方法必須是虛擬的,提高例外..如果方法呼叫提出這一例外 - 法未覆蓋 就像調用abstact方法會引發'EAbstractError'。它在子類中被重寫 - – teran 2012-02-26 14:12:23

+0

仍然在調試模式下,我如果聲明的方法'abstract'得到'摘要Error' ... – 2012-02-26 14:15:45

+0

。使他們全都是虛擬的並且聲明你自己的異常類型。 – teran 2012-02-26 14:17:59

回答

4

你可以做這樣的事情。請注意,我刪除了「抽象」。它可能適用於「抽象」,但我沒有嘗試過。

type 
    TMyClass = class(TObject) 
    protected 
    procedure VProc; virtual; 
    procedure VAProc; virtual; //abstract; 
    end; 


function GetVAProcAddress(Instance: TMyClass): pointer; 
var 
    p: procedure of object; 
begin 
    p := Instance.VAProc; 
    result := TMethod(p).Code; 
end; 


//in one of the TMyClass methods you can now write: 

    if GetVAProcAddress(self) <> @TMyClass.VAProc then 
+0

+1現在給它一個旋轉...... – 2012-02-26 14:21:18

+5

這是工作的一個可笑的金額 - 只需調用方法。如果它沒有被覆蓋的行爲來替換基類定義的非操作行爲,那麼只要允許調用no-op即可。這幾乎可以肯定是「更便宜」(並且更安全,如果您需要在未來推出基本類實現,您希望被稱爲),而不是像這樣跳過。 – Deltics 2012-02-27 00:34:35

1

使用RTTI得到虛方法的方法地址問題在提問的類。將它與基類的相同方法的方法地址進行比較。如果不相同,則該方法被覆蓋。

+2

+1聽起來很有希望,如果我能有一些鏈接或樣品... – 2012-02-26 14:03:55

+0

...因爲我從來沒有使用RTTI ... – 2012-02-26 14:12:17

+3

抵制誘惑,沉迷於針對簡單問題的奇特解決方案。做你所需要的 - 實現虛擬的非抽象方法,只需調用它們而不必擔心它們是否被覆蓋。正如你自己所說 - 被覆蓋是好的,但不會被覆蓋,所以爲什麼要關心這種或那種方式?唯一一次這成爲一個問題是,如果方法被(錯誤地)標記爲抽象的,在這種情況下它不表示你的設計(抽象方法必須被覆蓋,這是違揹你的需要的)。 – Deltics 2012-02-27 00:36:53

4

我認爲這是錯誤的做法,它聞起來真的很糟糕。一些建議:

  • 使用非抽象方法要在不重寫他們做什麼做的。
  • 使用事件而不是方法。檢查他們是否被分配很容易。
+0

注意1理解,注2不可能,因爲這是線程執行我在說 - 我不能使用事件的某些原因。 – 2012-02-26 17:26:31

1

如果你有一行這樣的代碼:

lObj := TMyClass.Create; 

你會發現,編譯器將輸出一個警告,說你正在構建的「TMyClass」包含抽象方法TMyClass.VAProc實例。

+3

甚至更​​好,配置編譯器把該爲錯誤而不是警告 – 2012-02-26 20:25:54

+0

你能做到這一點在Delphi XE2?無論哪種方式,都不需要混淆運行時異常,因爲如果嘗試調用抽象方法,則已經出現抽象錯誤。如果目標是在編譯時檢測到這種調用,編譯器已經爲您做了這些。 – 2012-02-26 21:34:29

+0

您也可以在早期版本中使用它。警告可以配置爲被忽略,警告或錯誤。非常便利。 – 2012-02-26 22:08:50

4

可以或可以不被覆蓋的方法不是一個抽象方法,它僅僅是虛擬

抽象方法是沒有基地實現,並且實現必須由後代提供。

在你的情況下,簡單地將它們聲明爲虛擬併爲他們提供的NO-OP(無操作)默認實現你的設計決定:

type 
    TMyBaseClass = class 
    protected 
     procedure SomeProc; virtual; 
    end; 


procedure TMyBaseClass.SomeProc; 
begin 
    // NO-OP 
end; 

注 - 這說明我個人的約定記錄一個故意的NO-OP,而不是隻留下一個空的實現。

你辦理任何shennanigans嘗試檢測聲明的抽象方法是否已經被覆蓋或不併調用它 - 或不 - 該測試的基礎上,可能比簡單地調用一個NO-花費更多的時間OP實施。另外,如果您需要在該基類中引入實現,則不必將該方法從抽象方法更改爲非抽象方法(可能會破壞那些您使用該方法的「檢測」電路,並且肯定會將其成本視爲無但純粹的開銷)。

+0

+1很高興看到我們完全達成協議,但情況並非總是如此;-) – 2012-02-27 07:29:01

+0

+1一致認爲,沒有必要對這種問題進行異化解決 - 如果沒有被覆蓋,它是一個無操作。 – 2012-02-27 18:24:51