我正在尝试为我的项目创建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中的泛型。我在这里缺少什么?
答案 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)" )
}