使用“类”数据类型时,如何指定类型以便只接受特定类的子类?

Posted

技术标签:

【中文标题】使用“类”数据类型时,如何指定类型以便只接受特定类的子类?【英文标题】:When using the 'Class' datatype, how can I specify the type so I only accept subclass of a specific class? 【发布时间】:2015-03-28 03:04:31 【问题描述】:

我有一个接受Class 类型参数的方法,我只想接受扩展SuperClass 的类。现在,我能想到的就是这个,它对实例进行运行时检查:

public function careless(SomeClass:Class):void 
    var instance:SomeClass = new SomeClass();
    if (instance as SuperClass) 
        // great, i guess
     else 
        // damn, wish i'd have known this at compile time
    


有没有办法做这样的事情,所以我可以确定Class 实例扩展了一些超类?

public function careful(SomeClass:[Class extends SuperClass]):void 
    var instance:SuperClass = new SomeClass();
    // all is good

【问题讨论】:

不太可能 - 虽然我不明白你为什么要这样实例化。为什么不先做function careful(instance:SuperClass) 然后做careful(new MySubClass()),如果不是子类,它会在你身上编译时出错。 你需要使用你为某事创建的实例,还是你创建它只是为了检查它是否是一个子类?你能不能只传入一个你知道是子类的新创建的对象并使用它? @mfa 可能有更好的方法来构建我正在处理的应用程序,但是按照所有设置的方式,我需要传入一个 Class 以便它可以通过以下方式多次实例化其他对象稍后。上面的具体代码只是为了展示一个简单的例子。 【参考方案1】:

如果你还是要实例化它,为什么不接受一个允许你输入:SuperClass的对象呢?

careless(SomeClass);
//vs.
careless(new SomeClass);

就您的代码而言,这并不是什么大问题。 不过还是有一些区别:

必须创建对象,因为需要一个对象。如果您的函数在某些情况下没有实例化该类,这可能是个问题。传递对象或 null 的附加逻辑可能会使函数调用膨胀。 如果您不能在该函数之外调用构造函数,它不会 也可以工作。

工厂模式解决了所有问题。传递一个工厂作为产生SuperClass 对象的参数。

function careful(factory:SuperClassFactory)

【讨论】:

我对工厂模式不是很熟悉 - 打算研究一下,因为它可能确实是我正在寻找的。​​span> 工厂模式正是我在这个应用程序中所需要的。谢谢!【参考方案2】:

您的要求:

我只想接受扩展 SuperClass 的类

我需要传入一个类,这样它就可以被实例化多次 稍后由其他对象

可以通过传入你需要的类的实例,并使用 Object.constructor() 方法来满足。

public function careful(someInstance:SuperClass):void 
    //you probably want to store classRef in a member variable
    var classRef: Class = someInstance.constructor();

    //the following is guaranteed to cast correctly,
    //since someInstance will always be a descendant of SuperClass  
    var myInst:SuperClass = new classRef() as SuperClass; 

More reading here.

【讨论】:

这是一个很好的解决方案。也许唯一的问题是它需要创建一个一次性实例?我最终使用工厂模式来解决我的特定问题,我认为这会让我不再需要使用它。不过,谢谢!【参考方案3】:

在 ActionScript 3 中你不能这样做。在像 C# 这样的语言中你可以这样做(如果语法关闭,请原谅我):

public void Careless<T>() where T : SuperClass

但是 AS3 没有“泛型”。不幸的是,我知道如何做你想做的事情的唯一方法就是你已经做过的事情。

可能更适合您的用例的模式可能类似于:

class SuperClass

    public static function careless():void
    
       var instance:SuperClass = new SuperClass();

       // ...
    

在 ActionScript 3 中进行静态类型检查的唯一方法是提供一个类的实例

【讨论】:

【参考方案4】:

这是可能的,但它很昂贵。您可以在类(而非实例)上使用:

flash.utils.describeType

然后,您将获得一个包含大量信息的 XML,包括该类的继承。就像我说的那样,这是一个昂贵的过程,并且可能在大多数情况下创建一个实例并检查它会更快。

【讨论】:

那是在运行时。 问题是基于运行时的,所有答案也是如此,你的意思是什么? 问题是问如何避免运行时检查,答案是尝试提供静态类型检查。 您自己的答案是基于运行时的。 PO 示例是基于运行时的。创建一个类的实例属于基于运行时的检查而不是编译时间。我的答案是您可以获得的最接近编译时检查的方法,因为它是唯一无需创建类实例即可工作的方法。 创建实例是基于运行时的,但如果在您的代码中您可能会创建错误类的实例,编译器会选择它,而您的示例需要在运行时检查 XML...你明白我的意思吗?

以上是关于使用“类”数据类型时,如何指定类型以便只接受特定类的子类?的主要内容,如果未能解决你的问题,请参考以下文章

StringBuffer 类,以及 StringBuilder 类

Postgresql 运算符类“varchar_pattern_ops”不接受数据类型整数

Scala的泛型

序列化特定类型时如何使 JSON.Net 序列化程序调用 ToString()?

mypy 是不是有子类可接受的返回类型?

Lmax Disruptor,许多消费者 - 如何让消费者只接受特定类型的消息并独立进行?