在Swift中可以吗?如果不是,那么是否有解决方法?


当前回答

带有协议继承的纯Swift方法:

//Required methods
protocol MyProtocol {
    func foo()
}

//Optional methods
protocol MyExtendedProtocol: MyProtocol {
    func bar()
}

class MyClass {
    var delegate: MyProtocol
    func myMethod() {
        (delegate as? MyExtendedProtocol).bar()
    }
}

其他回答

下面是一个使用委托模式的具体示例。

设置您的协议:

@objc protocol MyProtocol:class
{
    func requiredMethod()
    optional func optionalMethod()
}

class MyClass: NSObject
{
    weak var delegate:MyProtocol?

    func callDelegate()
    {
        delegate?.requiredMethod()
        delegate?.optionalMethod?()
    }
}

将委托设置为类并实现协议。请注意,不需要实现可选方法。

class AnotherClass: NSObject, MyProtocol
{
    init()
    {
        super.init()

        let myInstance = MyClass()
        myInstance.delegate = self
    }

    func requiredMethod()
    {
    }
}

重要的一点是,可选方法是可选的,在调用时需要“?”。提到第二个问号。

delegate?.optionalMethod?()

如果你想在纯swift中做到这一点,最好的方法是提供一个默认实现,特别是如果你返回一个swift类型,例如struct与swift类型

例子:

struct magicDatas {
    var damagePoints : Int?
    var manaPoints : Int?
}

protocol magicCastDelegate {
    func castFire() -> magicDatas
    func castIce() -> magicDatas
}

extension magicCastDelegate {
    func castFire() -> magicDatas {
        return magicDatas()
    }

    func castIce() -> magicDatas {
        return magicDatas()
    }
}

然后你可以实现协议而不定义每个func

由于有一些关于如何使用可选修饰符和@objc属性来定义可选需求协议的答案,我将给出一个如何使用协议扩展定义可选协议的示例。

下面的代码是Swift 3.*。

/// Protocol has empty default implementation of the following methods making them optional to implement:
/// `cancel()`
protocol Cancelable {

    /// default implementation is empty.
    func cancel()
}

extension Cancelable {

    func cancel() {}
}

class Plane: Cancelable {
  //Since cancel() have default implementation, that is optional to class Plane
}

let plane = Plane()
plane.cancel()
// Print out *United Airlines can't cancelable*

请注意,Objective-C代码不能调用协议扩展方法,更糟糕的是Swift团队不会修复它。https://bugs.swift.org/browse/SR-492

这里的其他答案涉及将协议标记为“@objc”,在使用swift特定类型时不起作用。

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"

为了声明能在swift中很好地工作的可选协议,将函数声明为变量而不是func。

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

然后实现如下协议

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)?
}

然后可以使用“?”来检查函数是否已经实现

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

var anEntity: Health = returnEntity()

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

我认为在询问如何实现一个可选协议方法之前,应该先问问为什么要实现它。

如果我们将swift协议视为经典的面向对象编程中的接口,那么可选方法就没有多大意义,也许更好的解决方案是创建默认实现,或将协议分离为一组协议(可能在它们之间具有一些继承关系),以表示协议中方法的可能组合。

欲进一步阅读,请参阅https://useyourloaf.com/blog/swift-optional-protocol-methods/,该网站对此问题有很好的概述。