aeu*_*nks 70 protocols subclassing swift swift-protocols
我有一个协议P,它返回一个对象的副本:
protocol P {
func copy() -> Self
}
Run Code Online (Sandbox Code Playgroud)
以及实现P的C类:
class C : P {
func copy() -> Self {
return C()
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我是否输入返回值,因为Self我得到以下错误:
无法将类型为"C"的返回表达式转换为返回类型"Self"
我也试过回来了C.
class C : P {
func copy() -> C {
return C()
}
}
Run Code Online (Sandbox Code Playgroud)
这导致以下错误:
非终结类'C'中的方法'copy()'必须返回
Self以符合协议'P'
没有什么可行的,除了我前缀class C为finalie 的情况:
final class C : P {
func copy() -> C {
return C()
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我想继承C,那么什么都行不通.有没有办法解决?
Rob*_*ier 140
问题是你承诺编译器无法证明你会保留.
所以你创造了这个承诺:调用copy()将返回自己的类型,完全初始化.
但是你实现了copy()这种方式:
func copy() -> Self {
return C()
}
Run Code Online (Sandbox Code Playgroud)
现在我是一个不会覆盖的子类copy().而且我返回了一个C,而不是一个完全初始化的Self(我承诺过).所以这不好.怎么样:
func copy() -> Self {
return Self()
}
Run Code Online (Sandbox Code Playgroud)
好吧,那不会编译,但即使它确实如此,也没有好处.子类可能没有普通的构造函数,所以D()甚至可能不合法.(虽然见下文.)
好吧,那怎么样:
func copy() -> C {
return C()
}
Run Code Online (Sandbox Code Playgroud)
是的,但这不会回来Self.它回来了C.你还没有履行诺言.
"但是ObjC可以做到!" 好吧,有点.主要是因为它并不关心你是否像Swift那样遵守诺言.如果未能copyWithZone:在子类中实现,则可能无法完全初始化对象.编译器甚至不会警告你,你已经这样做了.
"但ObjC中的大部分内容都可以翻译成Swift,ObjC也可以NSCopying." 是的确如此,以下是它的定义:
func copy() -> AnyObject!
Run Code Online (Sandbox Code Playgroud)
所以你也可以这样做(这里没有理由!)
protocol Copyable {
func copy() -> AnyObject
}
Run Code Online (Sandbox Code Playgroud)
这说:"我对你得到的东西没有任何承诺." 你也可以说:
protocol Copyable {
func copy() -> Copyable
}
Run Code Online (Sandbox Code Playgroud)
这是你可以做出的承诺.
但我们可以暂时考虑一下C++并记住我们可以做出的承诺.我们可以保证我们和我们所有的子类都将实现特定类型的初始化器,Swift将强制执行(因此可以证明我们说实话):
protocol Copyable {
init(copy: Self)
}
class C : Copyable {
required init(copy: C) {
// Perform your copying here.
}
}
Run Code Online (Sandbox Code Playgroud)
这就是你应该如何进行复制.
我们可以更进一步,但它使用了dynamicType,我没有广泛测试它以确保它始终是我们想要的,但它应该是正确的:
protocol Copyable {
func copy() -> Self
init(copy: Self)
}
class C : Copyable {
func copy() -> Self {
return self.dynamicType(copy: self)
}
required init(copy: C) {
// Perform your copying here.
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们保证有一个初始化器为我们执行复制,然后我们可以在运行时确定要调用哪个,给我们您正在寻找的方法语法.
Tol*_*kur 24
使用Swift 2,我们可以使用协议扩展.
protocol Copyable {
init(copy:Self)
}
extension Copyable {
func copy() -> Self {
return Self.init(copy: self)
}
}
Run Code Online (Sandbox Code Playgroud)
小智 14
还有另一种方法可以做你想要的,包括利用Swift的相关类型.这是一个简单的例子:
public protocol Creatable {
associatedtype ObjectType = Self
static func create() -> ObjectType
}
class MyClass {
// Your class stuff here
}
extension MyClass: Creatable {
// Define the protocol function to return class type
static func create() -> MyClass {
// Create an instance of your class however you want
return MyClass()
}
}
let obj = MyClass.create()
Run Code Online (Sandbox Code Playgroud)
wer*_*ver 10
实际上,有一个技巧可以在协议(gist)需要时轻松返回:Self
/// Cast the argument to the infered function return type.
func autocast<T>(some: Any) -> T? {
return some as? T
}
protocol Foo {
static func foo() -> Self
}
class Vehicle: Foo {
class func foo() -> Self {
return autocast(Vehicle())!
}
}
class Tractor: Vehicle {
override class func foo() -> Self {
return autocast(Tractor())!
}
}
func typeName(some: Any) -> String {
return (some is Any.Type) ? "\(some)" : "\(some.dynamicType)"
}
let vehicle = Vehicle.foo()
let tractor = Tractor.foo()
print(typeName(vehicle)) // Vehicle
print(typeName(tractor)) // Tractor
Run Code Online (Sandbox Code Playgroud)
Swift 5.1 现在允许强制转换为 Self,as! Self
给定
protocol P {
func id() -> Self
}
Run Code Online (Sandbox Code Playgroud)
这有效:
class D : P {
func id() -> Self {
return D() as! Self
}
}
Run Code Online (Sandbox Code Playgroud)
如果没有as! Self,您会收到错误:
error: repl.swift:11:16: error: cannot convert return expression of type 'D' to return type 'Self'
return D()
^~~
as! Self
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24724 次 |
| 最近记录: |