泛型在Swift中使用Type T调用

编程入门 行业动态 更新时间:2024-10-28 12:15:44
本文介绍了泛型在Swift中使用Type T调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

在我的应用程序中,我想创建一个泛型方法,它创建一个对象数组,并根据给定的类型T创建一个对象数组。我创建了以下函数:

func getArray< T:ROJSONObject>(key:String) - >对于getValue(key).array中的jsonValue,T [] { var elements = T []() ! { var element = T() element.jsonData = jsonValue elements.append(element)} 返回元素}

现在我想在调用方法时传递该类型,所以它知道它应该在内部创建它的类型。我认为在Java和C#中你可以使用类似的方法: pre $ object $ object $ getArray< Document>(key)

当我这样称呼它时,我总是得到错误:

不能明确地专用一个通用函数

所以我的解决方法是定义一个包含T类型实例的附加参数,以便它自动检测类型:

func getArray< ; T:ROJSONObject>(key:String,type:T) - >对于getValue(key).array中的jsonValue,T [] { var elements = T []() ! { var element = T() element.jsonData = jsonValue elements.append(element)} 返回元素}

真的没有其他方法可以在不传递未使用的实例的情况下获得该行为吗?或者我误吞东西?

进一步测试

在jtbandes我做了更多的测试。我尝试通过在调用中添加作为来强制使用Type。

class Person { init(){} func getWorkingHours() - > Float { return 40.0 } } class Boss:Person { override func getWorkingHours() - > Float { println(100.0) return 100.0 } } 类Worker:Person {覆盖func getWorkingHours() - > ; Float { println(42.0) return 42.0 } } func getWorkingHours< T:Person>() - > T { var person = T() person.getWorkingHours() return person } var worker:Worker = getWorkingHours ()as Worker var boss:Boss = getWorkingHours()as Boss worker.getWorkingHours()//输出40.0而不是42.0 boss.getWorkingHours()//输出40.0代替100.0

因此,类型总是基本类型,即使我已经用作为关键字。我知道这个例子没有多大意义,但它只是为了测试目的。

解决方案

我认为这是一个bug 。

你可以通过使类成为 NSObject 的子类或者用基类的标记构造函数来解决它 @required

import Cocoa class A:NSObject { init(){} } class B:A {} $ b $ class class C:A {} func Create< T :NSObject的> () - > T { return T()} println(Create()as A) println(Create()as B) println(Create ()as C) //< _TtC11lldb_expr_01A:0x7f85ab717bc0> //< _TtC11lldb_expr_01B:0x7f85ab451e00> //< _TtC11lldb_expr_01C:0x7f85ab509160> class D { @required init(){} } class E:D { init(){} class F:D { init(){} } func Create2< T:D> () - > T { return T()} println(Create2()as D) println(Create2()as E) println(Create2 ()as F) // C11lldb_expr_01D(有0个孩子) // C11lldb_expr_01E(有1个孩子) // C11lldb_expr_01F(有1个孩子)

不知道为什么 @required 解决问题。但这是参考资料

必填

将此属性应用于类的指定或便利初始值设定项,以指示每个子类必须实现初始值设定项。

必需的指定初始值设定项必须明确实施。 所需的便利初始值设定项既可以显式实现,也可以在子类直接实现所有超类的指定初始值设定项时继承(或者当子类使用便捷初始值设定项覆盖指定初始值设定项时) 。

In my application I want to create an generic method which creates an array of object depening on the given type T.

I created the following function:

func getArray<T : ROJSONObject>(key:String) -> T[] { var elements = T[]() for jsonValue in getValue(key).array! { var element = T() element.jsonData = jsonValue elements.append(element) } return elements }

Now I want to pass the type when I call the method, so it does know which type it should create internally. I think in Java and C# you can use a method like that:

object.getArray<Document>("key")

When I call it like that, I always get the error:

Cannot explicitly specialize a generic function

So my fix was to define an additional parameter containing an instance of the type T so it does automatically detect the type:

func getArray<T : ROJSONObject>(key:String, type:T) -> T[] { var elements = T[]() for jsonValue in getValue(key).array! { var element = T() element.jsonData = jsonValue elements.append(element) } return elements }

Is there really no other way to get that behaviour without passing an unused instance? Or am I misunterstanding something?

Further Testing

After the answer of jtbandes I did some more testing. I tried to force the Type by adding the as in the call.

class Person { init() { } func getWorkingHours() -> Float { return 40.0 } } class Boss : Person { override func getWorkingHours() -> Float { println(100.0) return 100.0 } } class Worker : Person { override func getWorkingHours() -> Float { println(42.0) return 42.0 } } func getWorkingHours<T : Person>() -> T { var person = T() person.getWorkingHours() return person } var worker:Worker = getWorkingHours() as Worker var boss:Boss = getWorkingHours() as Boss worker.getWorkingHours() // prints out 40.0 instead of 42.0 boss.getWorkingHours() // prints out 40.0 instead of 100.0

So somehow the type is always the base type even I've specified the type with the as keyword. I know the example does not make much sense, but it was just for testing purpose..

解决方案

I think it is a bug.

You can work around it by making the class a sub-class of NSObject or mark constructor of base class with @required

import Cocoa class A : NSObject { init() { } } class B : A {} class C : A {} func Create<T:NSObject> () -> T { return T() } println(Create() as A) println(Create() as B) println(Create() as C) //<_TtC11lldb_expr_01A: 0x7f85ab717bc0> //<_TtC11lldb_expr_01B: 0x7f85ab451e00> //<_TtC11lldb_expr_01C: 0x7f85ab509160> class D { @required init() { } } class E : D { init() { } } class F : D { init() { } } func Create2<T:D> () -> T { return T() } println(Create2() as D) println(Create2() as E) println(Create2() as F) //C11lldb_expr_01D (has 0 children) //C11lldb_expr_01E (has 1 child) //C11lldb_expr_01F (has 1 child)

Not sure why @required solve the problem. But this is the reference

required

Apply this attribute to a designated or convenience initializer of a class to indicate that every subclass must implement that initializer.

Required designated initializers must be implemented explicitly. Required convenience initializers can be either implemented explicitly or inherited when the subclass directly implements all of the superclass’s designated initializers (or when the subclass overrides the designated initializers with convenience initializers).

更多推荐

泛型在Swift中使用Type T调用

本文发布于:2023-11-10 10:24:43,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Swift   Type

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!