gpt4 book ai didi

swift - 满足 ExpressibleByArrayLiteral 协议(protocol)

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

为什么当我在 swift 中扩展 ExpressibleByArrayLiteral 协议(protocol)时,我需要使 init 成为必需的。在协议(protocol)的定义中,init 方法只是公开的。

我和文档中的内容差不多,https://developer.apple.com/reference/swift/expressiblebyarrayliteral ,而且编译器仍然提示使这个 init(arrayLiteral: Element...) 成为必需的。我唯一的区别是我在一个没有结构的类中实现它。有什么建议吗?

更新:

这是我的代码的实现:

public class Stack<T> {
private var buffer: [T]

init() {
self.buffer = []
}

public func push(_ value: T) {
self.buffer.append(value)
}

public func pop() -> T? {
return self.buffer.popLast()
}

var size: Int {
return self.buffer.count
}

var isEmpty: Bool {
return self.size == 0
}
}

extension Stack: ExpressibleByArrayLiteral {
init(arrayLiteral: T...) {
for item in arrayLiteral {
self.push(item)
}
}
}

我得到的错误是:

1) 不能在'Stack'的扩展中声明指定的构造器;你是说这是一个方便的初始化程序吗?

2) 初始化程序 'init(arrayLiteral:)' 必须公开,因为它符合公共(public)协议(protocol) 'ExpressibleByArrayLiteral' 中的要求

3) 初始化器要求 'init(arrayLiteral:)' 只能由非最终类 'Stack' 定义中的 required 初始化器满足

问题:

对于错误 #1 -> 为什么我不能在扩展中声明指定的 init?

对于错误 #2 -> 我理解这部分,协议(protocol)将其定义为公开的。但是为什么文档在没有 public 关键字的情况下实现它?

对于错误 #3 -> 这几乎是我最大的问题,为什么需要这样做。

感谢您的帮助!

最佳答案

原因是继承:如果被类采用,则协议(protocol)中的任何 init 都必须标记为 requiredstruct 不能被继承。

对于一个类,init 必须初始化同一个类的一个实例或返回nil。当该类采用协议(protocol)时,它本身及其所有子类都必须提供自己的实现,以便编译器可以验证这一事实:

class ClassA : ExpressibleByArrayLiteral {
required init(arrayLiteral elements: Self.Element...) {
// this implicitly returns an instance of ClassA
}
}

class ClassB : ClassA {
// without its own init(arrayLitteral:), it will fallback on ClassA's init and return
// an instance of ClassA, which Swift does not allow.
}

这是由于 Swift 的静态类型系统。不像在 Objective-C 中,你认为你创建了一个 NSString 但实际上得到了一个 _NSContiguousString (所谓的 class cluster 设计模式)

NSString * str = [[NSString alloc] initWithString:@"Hello world"];
// surprise: you may get an _NSContiguousString instead

只需删除扩展并在类的定义中实现它:

public class Stack<T> : ExpressibleByArrayLiteral {
private var buffer: [T]

init() {
self.buffer = []
}

public func push(_ value: T) {
self.buffer.append(value)
}

public func pop() -> T? {
return self.buffer.popLast()
}

var size: Int {
return self.buffer.count
}

var isEmpty: Bool {
return self.size == 0
}

// MARK: -
required public init(arrayLiteral: T...) {
self.buffer = []
for item in arrayLiteral {
self.push(item)
}
}
}

关于swift - 满足 ExpressibleByArrayLiteral 协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42675940/

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