假设我有一个名为public static class FSharpOption {
public static FSharpOption<T> Create<T>(T value) {
return new FSharpOption<T>(value);
}
public static bool IsSome<T>(this FSharpOption<T> opt) {
return FSharpOption<T>.get_IsSome(opt);
}
public static bool IsNone<T>(this FSharpOption<T> opt) {
return FSharpOption<T>.get_IsNone(opt);
}
}
的协议,其中包含一个名为MyProtocol
的可选方法:
opt()
我还有一个名为@objc protocol MyProtocol {
func req() -> Int;
optional func opt() -> Int;
}
的包装类:
MyProtocolWrapper
在方法@objc class ProtocolWrapper : NSObject, MyProtocol{
let delegate : MyProtocol
init(delegate : MyProtocol){
self.delegate = delegate
}
func req() -> Int {
//doSomeWorkBeforeReq
let r = delegate.req()
//doSomeWorkAfterReq
return r
}
func opt() -> Int {
return delegate.opt?() //compiler error because Int? is required as return type
}
}
中,如何返回ProtocolWrapper.opt()
可能返回且仍符合delegate.opt?()
协议的可选值?
感谢您的帮助,
答案 0 :(得分:1)
我看到了3种可能的解决方案:
optional func opt() -> Int
替换为optional func opt() -> Int?
ProtocolWrapper
返回默认值。将return delegate.opt?()
替换为返回delegate.opt?() ?? 0
。 0
就是例如。替换
@objc protocol MyProtocol {
func req() -> Int;
optional func opt() -> Int;
}
与
protocol MyProtocol {
func req() -> Int
func opt() -> Int
}
extension MyProtocol {
//default implementation here
func opt() -> Int {
return 0
}
}
P.S。如果您继承自NSObject
,则无需在课前编写@objc
P.P.S。如果您使用选项3,则可以创建纯swift类(不包含NSObject
和@objc
)
答案 1 :(得分:1)
首先直接解决您的问题:
如何返回delegate.opt?()可能返回的可选值,并且仍然符合MyProtocol协议?
要使req()
传播可选值,必须将其声明为返回可选值。 req()
的实现包含返回Int?
的语句,但这并未改变将请求声明为Int
的事实。
在这里你的例子中包含一些主要的奇怪之处并不值得,这些奇怪之处都没有本身的无效,但肯定会引起混乱。
您似乎尝试使用相同的协议(MyProtocol
)用于两个不同的目的。虽然它会非常干净&#34;统一您的公共和私人接口&#39;将名称合并为一个,这实际上并没有为您的代码带来任何好处(您发布的问题是一个很好的例子)。
@objc protocol MyProtocol {
func req() -> Int?
}
@objc protocol MyProtocolOptionals {
optional func req() -> Int
}
@objc class ProtocolWrapper : NSObject, MyProtocol {
let delegate : MyProtocolOptionals
func opt() -> Int? { return delegate.opt?() }
}
一般来说,Objective-C协议(包括optional
属性)在Swift中实现,主要是为了围绕它们设计的旧代码库。理想情况下,新代码将采用Swift的本机语义。例如,optional
方法的替代方案是协议扩展,它提供方法的默认实现,以符合不声明自己的类型:
protocol MyProtocolOptionals {
func req() -> Int?
}
extension MyProtocolOptionals {
func req() -> Int? { return nil }
}
@objc MyNonImplementing: MyProtocolOptionals {
}
@objc MyImplementing: MyProtocolOptionals {
func req() -> Int? { return true.hashValue }
}