为什么这个Swift代码没有编译?
protocol P { }
struct S: P { }
let arr:[P] = [ S() ]
extension Array where Element : P {
func test<T>() -> [T] {
return []
}
}
let result : [S] = arr.test()
Run Code Online (Sandbox Code Playgroud)
编译器说:"类型P
不符合协议P
"(或者,在Swift的更高版本中,"不支持使用'P'作为符合协议'P'的具体类型.").
为什么不?不知怎的,这感觉就像语言中的漏洞.我意识到问题源于将数组声明arr
为协议类型的数组,但这是不合理的事情吗?我认为协议正是为了帮助提供类似层次结构的结构?
我正在定义一个调用的协议PanelController
,我想在其中存储一个PanelView
.PanelView
它本身是一个子类,UIView
定义了面板的基本结构.我有一个子类三种不同的观点PanelView
:LeftPanel
,MidPanel
,和RightPanel
.对于每个面板,我想定义一个xxxPanelController
符合PanelController
协议的(左,中,右).
我遇到的问题是协议和 xxxPanelController
protocol PanelController {
var panelView: PanelView { get set }
...
}
Run Code Online (Sandbox Code Playgroud)
和
class LeftPanelController: UIViewController, PanelController {
var panelView = LeftPanelView()
...
}
Run Code Online (Sandbox Code Playgroud)
哪里
class LeftPanelView: PanelView {
...
}
Run Code Online (Sandbox Code Playgroud)
和(最后一件......)
class PanelView: UIView {
...
}
Run Code Online (Sandbox Code Playgroud)
我得到一个错误说:LeftPanelController does not conform to protocol PanelController
出于一个显而易见的原因:panelView
类型LeftPanelView
不是PanelView
.这似乎真的仅限于我,因为它LeftPanelView
是一个子类,PanelView
所以它应该工作!但事实并非如此! …
为什么不快速支持协议中定义的方法中的返回类型协变?例如
class Base { }
class Derived : Base { }
protocol Requirement {
var someVariable : Base { get }
}
struct MyStruct : Requirement{
let someVariable : Derived
}
Run Code Online (Sandbox Code Playgroud)
编译器会发出MyStruct不符合协议要求的错误.据我所知,MyStruct满足了LSP的所有要求,所以我想知道为什么Swift中不允许这样做?
[ 首先,如果有人对问题有更好的名称,提案就会被广泛接受.到目前为止,我没有找到更好的名称.]
所以,这就是问题所在.
假设我有一个协议ProtocolA
,协议ProtocolB
和协议ProtocolX
定义如下:
protocol ProtocolA {
func doSomethingA()
}
protocol ProtocolB {
func doSomethingB()
}
protocol ProtocolX {
var handler: ProtocolA { get }
}
Run Code Online (Sandbox Code Playgroud)
然后我在ProtocolX的一个类中有一个正确的实现,如下所示:
class Donald: ProtocolX {
...
var handler: ProtocolA { ... }
...
}
Run Code Online (Sandbox Code Playgroud)
然后一切正常,协议要求得到正确履行.
但
如果我这样实现:
class Donald: ProtocolX {
...
var handler: ProtocolA & ProtocolB
...
}
Run Code Online (Sandbox Code Playgroud)
我有一个编译时问题,报告我的类Donald
不符合ProtocolX
(根据规范,要求var handler
必须符合ProtocolA
).
从理论上讲,var handler
IS符合ProtocolA
(但它也符合ProtocolB …
我无法使用以下代码:
@objc protocol Child { }
@objc protocol Parent {
var child: Child { get }
}
class ChildImpl: Child {
func doSomething() { }
}
class ParentImpl: Parent {
let child = ChildImpl()
// this would solve the problem, however can't access the ChildImpl members
// that are not part of the protocol
// let child: Child = ChildImpl()
// as well as this, however maintaining two properties is an ugly hack
// var child: Child { return childImpl …
Run Code Online (Sandbox Code Playgroud) 我有一个已创建的协议(在Swift 4.2中),它的要求之一是与协议本身具有相同类型的属性。
例如,我有一个定义如下的协议:
protocol A {
var a: A? { get set }
}
Run Code Online (Sandbox Code Playgroud)
我有几个符合此协议的模型:
class Model1: A {
var a: A?
}
Run Code Online (Sandbox Code Playgroud)
class Model2: A {
var a: A?
}
Run Code Online (Sandbox Code Playgroud)
对于我的一个模型,我需要通过更具体地定义变量定义的属性a
(即具有协议类型的变量)来满足协议要求。因此,例如,我可能要实现Model2
为:
class Model2: A {
var a: Model1?
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,由于Model1
符合协议,因此A
您希望它能够满足协议要求,但是我收到一条错误消息:
类型“ Model2”不符合协议“ A”
为什么会发生这种情况,我该怎么做才能使其如上所述工作?
附录
(如果有人可以提出更好的标题,请这样做)
以下代码不会编译出错Type 'ObserverClass' does not conform to protocol 'Observer'
,编译器通过声明var object: ObservedObject
.
class ObservedObject {}
class ObservedObjectSubclass: ObservedObject {}
protocol Observer {
var object: ObservedObject { get }
}
class ObserverClass: Observer { // Type 'ObserverClass' does not conform to protocol 'Observer'
// suggested:
// var object: ObservedObject
var object: ObservedObjectSubclass = ObservedObjectSubclass()
}
Run Code Online (Sandbox Code Playgroud)
我的看法是 -ObservedObjectSubclass
是 ObservedObject
,所以object
财产保证是ObservedObject
协议要求的类型。
(同样如此,如果使用协议一致性而不是子类化 - 下面)
protocol ObservedObjectProtocol {}
protocol Observer {
var object: ObservedObjectProtocol { …
Run Code Online (Sandbox Code Playgroud) protocol BasePresenterProtocol : class {}
protocol DashboardPresenterProtocol : BasePresenterProtocol {}
final class DashboardPresenter {
weak var view: DashboardPresenterProtocol?
init() {
self.view = DashboardViewController()
}
func test() {
print("Hello")
}
}
extension DashboardPresenter: DashboardViewProtocol { }
protocol BaseViewProtocol : class {
weak var view: BasePresenterProtocol? { get set }
}
protocol DashboardViewProtocol : BaseViewProtocol {
}
class DashboardViewController {
}
extension DashboardViewController: DashboardPresenterProtocol { }
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,我在下一行收到错误
extension DashboardPresenter: DashboardViewProtocol { }
Run Code Online (Sandbox Code Playgroud)
那个,DashboardPresenter
不向协议确认DashboardViewProtocol
,但我已经宣布weak var view: DashboardPresenterProtocol?
了 …
swift ×8
protocols ×5
covariance ×1
generics ×1
ios ×1
objective-c ×1
oop ×1
subtype ×1
swift4 ×1
syntax ×1