gpt4 book ai didi

swift - 实现接受并返回 Self 的协议(protocol)静态方法( swift )

转载 作者:可可西里 更新时间:2023-11-01 01:14:43 26 4
gpt4 key购买 nike

给定一个类似这样的协议(protocol):

protocol Thing {
static func *(lhs: Float, rhs: Self) -> Self
}

如何实现盒子类?

class ThingBox<T: Thing>: Thing {
var thing: T
required init(thing: T) { self.thing = thing }
static func *(lhs: Float, rhs: Self) -> Self {
return Self(thing: lhs * rhs.thing)
}
}

编译器提示 Self不能在方法类型中使用,但事实是 ThingBox是可继承的意味着使用 ThingBox<T>不合适。

如果不强制它是 final 就不可能写这个类吗? ?

最佳答案

您的* 实现有一些细微的问题。这是您的意思:

static func *(lhs: Float, rhs: ThingBox<T>) -> Self {
return self.init(thing: lhs * rhs.thing)
}

首先,您不能将Self 用作参数类型。你必须明确。 Self 表示“实际类型”,如果您可以将其用于子类,这将违反 LSP .例如,假设我有类型 AnimalDog(具有明显的关系)。假设我写了函数:

class Animal {
func f(_ a: Self) { ... }
}

意思是 Animal.f 会带 Animal,但是 Dog.f 只会带 Dog不会带一只。所以您会期望以下内容为真:

dog.f(otherDog) // this works
dog.f(cat) // this fails

但这违反了替换规则。如果我这样写会怎样:

let animal: Animal = Dog()
animal.f(cat)

这应该是合法的,因为 Animal.f 可以接受任何 Animal,但是 Dog.f 的实现不能接受猫。类型不匹配。繁荣。所以这是不合法的。 (对于返回类型不存在此限制。我将把它留给读者作为练习。尝试创建一个类似上面的示例来返回 Self。)

第二个错误只是语法错误。这不是 Self(),而是 self.init()。在静态方法中,self 是动态类型(这是您想要的),Swift 要求您在以这种方式使用时显式调用 init。这只是语法,而不是像其他问题那样的深层类型问题。


Swift 无法继承您正在谈论的东西。如果你想重载,那很好,但你必须明确类型:

class OtherBox: ThingBox<Int> {
static func *(lhs: Float, rhs: OtherBox) -> Self {
return self.init(thing: lhs * rhs.thing)
}
}

这正是你想要的,但它必须添加到每个 child ;它不会通过协方差自动继承。 Swift 没有强大的协方差系统来表达它。

也就是说,当您开始以这种方式混合泛型、协议(protocol)和子类化时,您会遇到很多很多奇怪的极端情况,这既是由于数学原因,也是由于当前 Swift 的限制。您应该仔细询问您的实际代码是否需要这么多参数化。我遇到的大多数此类问题都是过度设计的“以防万一”,简化类型并使事情具体化就是解决要编写的实际程序所需的一切。并不是说在更高级类型的基础上构建令人难以置信的通用算法不好,但 Swift 不是今天的语言(而且可能永远不会;添加这些功能需要很多成本)。

关于swift - 实现接受并返回 Self 的协议(protocol)静态方法( swift ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46368841/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com