为什么我们需要一个通用的?这个协议不够吗?

时间:2017-06-06 10:47:39

标签: swift generics swift-protocols

我在网上发现了以下关于将泛型与协议一起使用的示例,但是当我们只需要使用协议时,我不明白为什么我们需要泛型。

我们定义了一个协议:

protocol Healthy {
    mutating func setAlive(status: Bool)
    var health: Int { get }
}

然后是一个使用通用adotping协议的函数

func check<T:Healthy>(inout object: T) {
    if (object.health <= 0) {
        object.setAlive(false)
    }
}

我已经更改了下面的代码,一切都还不错。

func check( object: inout Healthy) {
    if (object.health <= 0) {
        object.setAlive(status: false)
    }
}

或不?

我可以想到在那里使用泛型的唯一原因,如果协议具有关联类型并且它不能用作实例。

2 个答案:

答案 0 :(得分:1)

他们表达不同的东西。随着

func check(object: inout Healthy) {

object参数可以是任何符合 Healthy的实例。因此,你可以这样做:

protocol Healthy {}

struct Foo : Healthy {}
struct Bar : Healthy {}

func check(object: inout Healthy) {
    object = Bar()
}

var h: Healthy = Foo()
check(object: &h)
print(h) // Bar()

我们调用check(object:)并将h(其中包含Foo个实例)作为inout参数传递,但结果是h持有Bar 1}}实例。

您会注意到这意味着我们不能简单地使用具体类型check(object:)参数调用inout。以下内容无法编译:

var h = Foo()

// compiler error: Cannot pass immutable value as inout argument: 
// implicit conversion from 'Foo' to 'Healthy' requires a temporary
check(object: &h)

因为check(object:)可以将任意 Healthy符合要求的实例分配给object参数,该参数不能分配给Foo变量。< / p>

然而,

func check<T : Healthy>(object: inout T) {

object参数是符合Healthy的单个特定具体类型(并且在呼叫站点处满足此类型)。您不能只为其分配一个任意Healthy符合条件的实例,因为它可能与作为inout参数传递的变量类型不兼容。

因此,现在允许您使用具体类型的inout参数调用它。我们现在可以说:

protocol Healthy {
    var alive: Bool { get set }
}

struct Foo : Healthy {
    var alive: Bool
}
struct Bar : Healthy {
    var alive: Bool
}

func check<T : Healthy>(object: inout T) {

    object.alive = false

    // illegal
    // object = Bar()
}

var h = Foo(alive: true)
check(object: &h)

(注意h可以输入为Foo

因此,在大多数情况下,您可能希望将该方法设为通用,而不是使用协议类型inout参数,因为您可能希望处理具体类型。

答案 1 :(得分:0)

因为这是使用inout(ugh)并且没有返回值意味着不需要泛型。

当我在这个例子中使用泛型时,如果方法签名是这样的......

func check<T:Healthy>(object: T) -> T {
}

这将确保传入的对象类型和返回的类型是相同的类型。

如果没有通用名称,您可以传入...

的实例
struct A: Healthy {}

并返回...的实例

struct B: Healthy {}

嗯......也许inout的情况仍然如此。您是否可以创建符合协议的另一个结构并将object更改为新结构的实例?也许......以后必须检查一下。