满足 ExpressibleByArrayLiteral 协议 [英] Satisfying ExpressibleByArrayLiteral Protocol
问题描述
为什么当我在 swift 中扩展 ExpressibleByArrayLiteral 协议时,我需要使 init 成为必需.在协议的定义中,init 方法只是公开的.
Why when I extend the ExpressibleByArrayLiteral protocol in swift I need to make the init required. In the definition of the protocol, the init method is just public.
我与文档中的内容几乎相同,https://developer.apple.com/reference/swift/expressiblebyarrayliteral,而且编译器仍然抱怨需要这个 init(arrayLiteral: Element...)
.我唯一的区别是我在一个没有结构的类中实现它.有什么建议吗?
I pretty much have the same thing as in the doc, https://developer.apple.com/reference/swift/expressiblebyarrayliteral, and still, the compiler complains about making this init(arrayLiteral: Element...)
required. The only difference I have is that I am implementing it in a class no a struct. Any suggestions?
更新:
这是我的代码的实现:
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'的扩展中声明指定的初始化器;你的意思是这是一个方便的初始化程序吗?
1) designated initializer cannot be declared in an extension of 'Stack'; did you mean this to be a convenience initializer?
2) 初始化器 'init(arrayLiteral:)' 必须声明为 public,因为它符合公共协议 'ExpressibleByArrayLiteral' 中的要求
2) initializer 'init(arrayLiteral:)' must be declared public because it matches a requirement in public protocol 'ExpressibleByArrayLiteral'
3) 初始化器要求 'init(arrayLiteral:)' 只能由非最终类 'Stack' 定义中的 required
初始化器来满足
3) initializer requirement 'init(arrayLiteral:)' can only be satisfied by a required
initializer in the definition of non-final class 'Stack'
问题:
对于错误 #1 -> 为什么我不能在扩展中声明指定的 init?
For error #1 -> Why can't I declare a designated init in an extension?
对于错误 #2 -> 我理解这部分,协议将其定义为公开.但是为什么文档在没有 public 关键字的情况下实现它?
For error #2 -> I understand this part, the protocol defines this as public. But why does the docs implement it with out the public keyword?
对于错误 #3 -> 这几乎是我最大的问题,为什么需要这样做.
For error #3 -> This is pretty much my biggest question, why this needs to be required.
感谢您的帮助!
推荐答案
原因是继承:协议内的任何 init
必须标记为 required
如果被一个协议采用班级.struct
不能被继承.
The reason is inheritance: any init
inside a protocol must be marked as required
if adopted by a class. A struct
cannot be inherited.
对于一个类,init
必须初始化同一个类的实例或返回 nil
.当该类采用协议时,其自身及其所有子类必须提供自己的实现,以便编译器可以验证这一事实:
For a class, An init
must initialize an instance of that same class or return nil
. When that class adopts a protocol, itself and all its subclasses must provide their own implementations so the compiler can verify that fact:
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
(所谓的 类簇设计模式)
This is due to Swift's static typing system. Unlike in Objective-C where you think you create an NSString
but actually get an _NSContiguousString
instead (the so-called class cluster design pattern)
NSString * str = [[NSString alloc] initWithString:@"Hello world"];
// surprise: you may get an _NSContiguousString instead
<小时>
去掉扩展并在类的定义中实现它:
Just get rid of the extension and implement it in the class's definition:
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)
}
}
}
这篇关于满足 ExpressibleByArrayLiteral 协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!