2017-02-22 25 views
1

考慮一個類型層次結構,其中的基本對象是不通用的,但子類型是:如何在泛型中使用Nim的````運算符?

type 
    TestBase = ref object of RootObj 

    DerivedA = ref object of TestBase 
    DerivedB[T] = ref object of TestBase 
    field: T 

proc testProc(x: TestBase) = 
    if x of DerivedB: # <= what to do here 
    echo "it's a B!" 
    else: 
    echo "not a B" 

使用of運營商這樣不會編譯,因爲它要求object類型。什麼是工作,例如以匹配DerivedB[int]之類的特定類型,或者在T中使處理程序本身具有通用性,這在通過DerivedA時沒有意義。

有沒有辦法解決這個問題一般不訴諸方法和動態調度?

回答

4

這裏最簡單的解決方案是爲所有通用派生類型引入一個虛擬基類型,唯一的目的是協助進行這種檢查。下面是一個例子:

type 
    TestBase = ref object of RootObj 

    DerivedA = ref object of TestBase 

    # I'm using illustrative names here 
    # You can choose something more sensible 
    DerivedDetector = ref object of TestBase 

    DerivedB[T] = ref object of DerivedDetector 
    field: T 

proc testProc(x: TestBase) = 
    if x of DerivedDetector: # This will be true for all derived types 
    echo "it's a B!" 
    else: 
    echo "not a B" 

testProc DerivedB[int](field: 10) 
testProc DerivedA() 

該解決方案不會增加對象的大小,並沒有在典型代碼引入任何運行時間開銷。

如果您不能修改繼承層次結構(它可能是第三方庫的一部分),那麼基於系統模塊的getTypeInfo proc會有更爲複雜的解決方案。此proc返回一個不透明的指針,可用作該類型的標識符。您必須將所有派生類型及其標識符註冊到哈希表中(您可以在程序開始時執行此操作),然後使用它對運行時檢查輸入值的類型信息指針PROC。