具有通用方法的Swift协议:无效的实现声明

时间:2019-03-16 12:50:45

标签: swift generics

我在Swift中玩一些协议/通用的东西,我很好奇为什么下面的代码拒绝编译:

protocol MyProtocol {
    func value<T>() -> T
}

class StringImpl: MyProtocol {
    var string: String

    init() {
        self.string = "..."
    }

    init(string: String) {
        self.string = string
    }

    func value<String>() -> String {
        return self.string as! String
    }
}

class BoolImpl: MyProtocol {
    var value: Bool

    init() {
        self.value = false
    }

    init(value: Bool) {
        self.value = value
    }

    func value<Bool>() -> Bool {
        return self.value as! Bool
    }
}

有特定错误

error: invalid redeclaration of 'value()'
func value<Bool>() -> Bool {

这可能意味着我不能有协议通用方法的不同实现,但是我不清楚为什么会这样。

(我不是说强制类型转换为存在的通用类型阴影)

P.S。对于那些好奇的人,我可能会告诉我,我正在尝试制定一种不会与associatedtype混淆并且在某种程度上还是通用的协议。

4 个答案:

答案 0 :(得分:2)

您没问题,错误是var value,然后重新声明名称为func value<Bool>的函数,我只是更改了变量名,它就起作用了,错误清楚地表明

  

错误:“ value()”的无效重新声明

class BoolImpl: MyProtocol {
var bool: Bool

init() {
    self.bool = false
}

init(value: Bool) {
    self.bool = value
}

func value<Bool>() -> Bool {
    return self.bool as! Bool
}
}

答案 1 :(得分:2)

  

错误:“ value()”的无效重新声明

是这样的。您的方法与变量名称相同,并且返回相同的类型。因此,编译器告诉您这是不合法的。


无论如何,您应该考虑是否确实需要此方法。您可以将此value属性添加到协议中,看起来您的协议也需要associatedtype

protocol MyProtocol {
    associatedtype T
    var value: T { get set }
}

class StringImpl: MyProtocol {
    typealias T = String
    var value: T = "..."

    init(string: T) {
        value = string
    }
}

class BoolImpl: MyProtocol {
    typealias T = Bool
    var value: T = false

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

然后,如果您只需要对象的值,则只需获取value属性

someStringImpl.value
someBoolImpl.value

答案 2 :(得分:1)

问题在于“值”变量名与“值”函数名相同

class BoolImpl: MyProtocol {
    var storedValue: Bool

    init() {
        self.storedValue = false
    }

    init(value: Bool) {
        self.storedValue = value
    }

    func value<Bool>() -> Bool {
        return self.storedValue as! Bool
    }
}

答案 3 :(得分:1)

每个人似乎都没有抓住重点。

您似乎认为您的采用者

protocol MyProtocol {
    func value<T>() -> T
}

...解决泛型。他们不。他们只是重复通用。

例如,考虑一下您的

func value<String>() -> String {
    return self.string as! String
}

self.string是一个字符串。因此,问问自己为什么必须说as! String。这是因为您像T一样误用String作为占位符名称。如果使用废话,您将得到相同的结果:

func value<Stringgg>() -> Stringgg {
    return self.string as! Stringgg
}

也可以编译。您仍未解析通用名称,只需更改其名称即可。您避免关联类型的尝试失败。您的代码可以编译,但永远无法运行。