2017-02-22 21 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。