通用类调用函数

时间:2018-02-27 10:01:10

标签: swift

我正在尝试为我的项目创建API返回包装类的包装器。

这些是我的课程

class Wrapper<T> {

   let message = "Hello World"
   let wrapped = T.self
   public func getData() -> T.Type {
       return wrapped
   }
}

class Object {

   let number = 100
   public func getNumber() -> Int {
       return number
   }
}

class SecondObject {

   let name = "Second Object" 
   public func getName() -> String {
       return name
   }
}

我想要实现的是,有什么方法可以像这样调用Object函数

let example = Wrapper<Object>()
example.getData().getNumber() // <<-- This is not working
let secondExample = Wrapper<SecondObject>()
secondExample.getData().getName() // <<-- This is not working

我操场上的错误就是这个

error: instance member 'getNumber' cannot be used on type 'Object'

如果您注意到Wrapper类,则会有message属性,该属性将用于我的所有API返回对象模型

所以我的目标是,我可以简单地将Wrapper类与我的对象模型类一起调用,并只调用对象模型类中的函数。

我还在学习swift中的泛型。我在这里缺少什么?

3 个答案:

答案 0 :(得分:1)

您没有将wrapped设置为有用的内容。您需要将其设置为T的实例。因此,您可以将T传递给构造函数

class Wrapper<T>
{
    let wrapped: T

    init(wrapped: T)
    {
        self.wrapped = wrapped
    }
}

或者你可以让类构造一个T的实例,但是如果你想这样做,你需要告诉它如何构造实例。例如:

class Wrapper<T>
{
    let wrapped: T

    init()
    {
        self.wrapped = T() // << error!
    }
}

不会工作,因为编译器对T一无所知,即使它有init也没有。您可以使用协议更改它

protocol Initable 
{
    init()
}

class Wrapper<T: Initable>
{
    let wrapped: T

    init()
    {
        self.wrapped = T() 
    }
}

您可以使用扩展程序将协议应用于您喜欢的任何类型。在大多数情况下,扩展名可以为空,因为mot类型已经有init()方法。例如:

class MyClass
{
    init() { /* do stuff */ }
}

extension MyClass: Initable {}

class MyOtherClass
{
    init(number: Int) { /* do stuff */ }
}

extension MyOtherClass: Initable 
{
    init() { self.init(number: 0) }
}

另一个选择是为包装器的init提供一个闭包。

class Wrapper<T>
{
    let wrapped: T

    init(factory: ()-> T)
    {
        self.wrapped = factory()
    }
}

let w = Wrapper() { return Array<Int>() }

通常情况下,如果您想创建多个实例,即只保留对闭包的引用,并在每次需要新实例时调用它,您只会这样做。

答案 1 :(得分:0)

class Wrapper<T> {

    private var wrapped: T // Storing your object of T type

    init(value: T) { // init with instance of T
        wrapped = value
    }

    public func getData() -> T { //returning instance of T
        return wrapped
    }
}

class Object {

    let number = 100
    public func getNumber() -> Int {
        return number
    }
}

let o = Object()
let example = Wrapper(value: o) // Here we creating instance of Wrapper with instance of Object
example.getData().getNumber()

答案 2 :(得分:0)

在您的示例中,将包装的类型从非可选类型更改为可选的变量类型。

 class Wrapper {

    let message = "Hello World"
    var wrapped : T?

    public func getData() -> T? {
        return wrapped
    }

}

class Object {

    let number = 100
    public func getNumber() -> Int {
        return number
    }
}

class SecondObject {

    let name = "Second Object"
    public func getName() -> String {
        return name
    }
}

然后使用它如下



let example = Wrapper()
example.wrapped = Object()
let result1 = example.getData()?.getNumber() // ()
secondExample.wrapped = SecondObject()
let result2 = secondExample.getData()?.getName() 

if let val1 = result1 , let val2 = result2 {
    print("result1 = \(val1) result2 = \(val2)" )     
}