为什么我们需要在这里通用?协议不够? [英] Why do we need a generic here? Isn't the protocol enough?

查看:95
本文介绍了为什么我们需要在这里通用?协议不够?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在网上找到了关于将泛型和协议一起使用的例子,但是我不明白为什么我们需要泛型,当我们需要的只是使用协议时。



我们定义了一个协议:

 协议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)
}
}
pre>

我改变了下面的代码,一切都还好。

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

还是没有?



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

解决方案

他们表达了不同的东西。

  func check(object:inout Healthy){

对象参数可以是任何 健康符合实例。因此,您可以这样做:

  protocol健康{} 

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 实例。



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

  var h = Foo()

//编译器错误:无法将不可变的值作为inout参数传递:
//从'Foo'到'Healthy'的隐式转换需要临时
检查(object:& h)

因为 check(object:)可以指定任意 Healthy 将符合实例的对象参数,不可赋值给 Foo 变量。



但是,使用

  func check   

object 参数是符合 Healthy 的一个特定具体类型(并且此类型在呼叫站点处得到满足)。你不能仅仅为它分配一个任意的健康的符合实例,因为它可能与作为 inout

现在可以使用具体类型的 inout 参数来调用它。我们现在可以说:

 协议健康状况{
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

//非法
//对象= Bar()
}

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

(注意 h 可以输入为 Foo
因此在大多数情况下,您可能希望使该方法为泛型,而不是使用协议类型为 inout code>参数,因为您可能想要处理具体的类型。


I found the following example on the web about using generics together with protocols, however I don't understand why do we need generics at all, when all we need is to use a protocol.

We define a protocol:

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

And then a function using a generic adotping that protocol

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

I've changed the code as below and everything is still fine.

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

Or not?

The only reason I could think of to use a generic there, if it's a protocol has an associatedtype and it can't used as an instance.

解决方案

They express different things. With

func check(object: inout Healthy) {

The object argument can be any Healthy conforming instance. Therefore, you could do this:

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()

We called check(object:) and passed h (which holds a Foo instance) as the inout argument, but ended up with h holding a Bar instance.

You'll note that this means we cannot simply call check(object:) with a concrete-typed inout argument. The following doesn't compile:

var h = Foo()

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

Because check(object:) could assign an arbitrary Healthy conforming instance to the object argument, which is not assignable to a Foo variable.

However, with

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

The object argument is a single specific concrete type that conforms to Healthy (and this type is satisfied at the call-site). You cannot just assign an arbitrary Healthy conforming instance to it, as it might not be compatible with the variable type being passed as the inout argument.

This therefore now allows you to call it with a concrete-typed inout argument. We can now say:

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)

(note h is able to be typed as Foo)

So in most cases, you'll likely want to make the method generic rather than having a protocol-typed inout parameter, as you'll likely want to be dealing with concrete types.

这篇关于为什么我们需要在这里通用?协议不够?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆