如何在Swift协议中定义可选方法?

本文探讨了在Swift协议中定义可选方法的两种方式:使用默认实现(首选)和使用可选关键字`?`。第一种方法允许结构、枚举和非类类型遵循协议,但可能需要合理默认值。第二种方法不需要默认实现,但限制了协议仅适用于Objective-C兼容的类。两种方法在实现和检查可选方法时都有其优缺点。
摘要由CSDN通过智能技术生成

本文翻译自:How to define optional methods in Swift protocol?

Is it possible in Swift? 在Swift中有可能吗? If not then is there a workaround to do it? 如果没有,那么是否有解决方法?


#1楼

参考:https://stackoom.com/question/1cq14/如何在Swift协议中定义可选方法


#2楼

@optional放在方法或属性的前面。


#3楼

1. Using default implementations (preferred). 1.使用默认实现(首选)。

protocol MyProtocol {
    func doSomething()
}

extension MyProtocol {
    func doSomething() {
        /* return a default value or just leave empty */
    }
}

struct MyStruct: MyProtocol {
    /* no compile error */
}

Advantages 好处

  • No Objective-C runtime is involved (well, no explicitly at least). 不涉及Objective-C运行时 (至少没有明确地涉及 )。 This means you can conform structs, enums and non- NSObject classes to it. 这意味着您可以使其符合结构,枚举和非NSObject类。 Also, this means you can take advantage of powerful generics system. 同样,这意味着您可以利用强大的泛型系统。

  • You can always be sure that all requirements are met when encountering types that conform to such protocol. 当遇到符合此类协议的类型时, 您始终可以确保满足所有要求 It's always either concrete implementation or default one. 它始终是具体实现或默认实现。 This is how "interfaces" or "contracts" behave in other languages. 这就是“接口”或“合同”在其他语言中的行为方式。

Disadvantages 缺点

  • For non- Void requirements, you need to have a reasonable default value , which is not always possible. 对于非Void要求,您需要具有一个合理的默认值 ,但这并非总是可能的。 However, when you encounter this problem, it means that either such requirement should really have no default implementation, or that your you made a mistake during API design. 但是,当您遇到此问题时,这意味着该要求实际上应该没有默认实现,或者您在API设计期间犯了一个错误。

  • You can't distinguish between a default implementation and no implementation at all , at least without addressing that problem with special return values. 您无法区分默认实现和根本没有实现 ,至少没有用特殊的返回值解决该问题。 Consider the following example: 考虑以下示例:

     protocol SomeParserDelegate { func validate(value: Any) -> Bool } 

    If you provide a default implementation which just returns true — it's fine at the first glance. 如果您提供仅返回true的默认实现-乍一看就可以了。 Now, consider the following pseudo code: 现在,考虑以下伪代码:

     final class SomeParser { func parse(data: Data) -> [Any] { if /* delegate.validate(value:) is not implemented */ { /* parse very fast without validating */ } else { /* parse and validate every value */ } } } 

    There's no way to implement such an optimization — you can't know if your delegate implements a method or not. 无法实现这种优化-您不知道您的委托是否实现了一种方法。

    Although there's a number of different ways to overcome this problem (using optional closures, different delegate objects for different operations to name a few), that example presents the problem clearly. 尽管有多种方法可以解决此问题(使用可选的闭包,用于不同操作的不同委托对象等),但该示例清楚地提出了问题。


2. Using @objc optional . 2.使用@objc optional

@objc protocol MyProtocol {
    @objc optional func doSomething()
}

class MyClass: NSObject, MyProtocol {
    /* no compile error */
}

Advantages 好处

  • No default implementation is needed. 无需默认实现。 You just declare an optional method or a variable and you're ready to go. 您只需声明一个可选方法或变量,就可以使用了。

Disadvantages 缺点

  • It severely limits your protocol's capabilities by requiring all conforming types to be Objective-C compatible. 要求所有符合类型都必须与Objective-C兼容,从而严重限制了协议的功能 This means, only classes that inherit from NSObject can conform to such protocol. 这意味着,只有从NSObject继承的类才能遵循此类协议。 No structs, no enums, no associated types. 没有结构,没有枚举,没有关联的类型。

  • You must always check if an optional method is implemented by either optionally calling or checking if the conforming type implements it. 您必须始终通过可选调用或检查符合类型是否实现了可选方法来检查是否实现了可选方法 This might introduce a lot of boilerplate if you're calling optional methods often. 如果您经常调用可选方法,这可能会引入很多样板。


#4楼

  • You need to add optional keyword prior to each method. 您需要在每种方法之前添加optional关键字。
  • Please note, however, that for this to work, your protocol must be marked with the @objc attribute. 但是请注意,要使此功能起作用, 必须使用@objc属性标记您的协议。
  • This further implies that this protocol would be applicable to classes but not structures. 这进一步暗示该协议将适用于类而不适用于结构。

#5楼

The other answers here involving marking the protocol as "@objc" do not work when using swift-specific types. 使用Swift特定类型时,此处涉及将协议标记为“ @objc”的其他答案不起作用。

struct Info {
    var height: Int
    var weight: Int
} 

@objc protocol Health {
    func isInfoHealthy(info: Info) -> Bool
} 
//Error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C"

In order to declare optional protocols that work well with swift, declare the functions as variables instead of func's. 为了声明与swift一起使用的可选协议,请将函数声明为变量而不是func。

protocol Health {
    var isInfoHealthy: (Info) -> (Bool)? { get set }
}

And then implement the protocol as follows 然后实现协议如下

class Human: Health {
    var isInfoHealthy: (Info) -> (Bool)? = { info in
        if info.weight < 200 && info.height > 72 {
            return true
        }
        return false
    }
    //Or leave out the implementation and declare it as:  
    //var isInfoHealthy: (Info) -> (Bool)?
}

You can then use "?" 然后可以使用“?” to check whether or not the function has been implemented 检查功能是否已实现

func returnEntity() -> Health {
    return Human()
}

var anEntity: Health = returnEntity()

var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))? 
//"isHealthy" is true

#6楼

Here's a very simple example for swift Classes ONLY, and not for structures or enumerations. 这是一个非常简单的示例,仅用于快速类,而不用于结构或枚举。 Note that the protocol method being optional, has two levels of optional chaining at play. 请注意,协议方法是可选的,有两个级别的可选链接在起作用。 Also the class adopting the protocol needs the @objc attribute in its declaration. 同样,采用该协议的类在其声明中也需要@objc属性。

@objc protocol CollectionOfDataDelegate{
   optional func indexDidChange(index: Int)
}


@objc class RootView: CollectionOfDataDelegate{

    var data = CollectionOfData()

   init(){
      data.delegate = self
      data.indexIsNow()
   }

  func indexDidChange(index: Int) {
      println("The index is currently: \(index)")
  }

}

class CollectionOfData{
    var index : Int?
    weak var delegate : CollectionOfDataDelegate?

   func indexIsNow(){
      index = 23
      delegate?.indexDidChange?(index!)
    }

 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值