我有一个协议Vehicle及其扩展名,如下所示:
protocol Vehicle {
func Drive()
}
extension Vehicle {
func Stop() {
print("iiiich...")
}
}
我也有如下的Stop方法声明
struct Car: Vehicle {
func Drive() {
print("Can Drive")
}
func Stop() {
print("yo stop")
}
}
let myCar = Car()
myCar.Drive()
myCar.Stop()
但是它覆盖了Stop方法
// Output
// Can Drive
// yo stop
根据我的要求,我有时需要默认方法,有些时候需要重写方法定义
答案 0 :(得分:8)
嘿,我得到的答案是通过对象调用您的默认方法而不是overriddedn来遵循协议,因此我们可以根据需要调用这两种定义
let honda: Vehicle = Car()
honda.Drive()
honda.Stop()
// Output
// Can Drive
// iiiich..
当我们创建一个没有类型的变量时,当对象仅符合协议时,这就是静态分配。
答案 1 :(得分:4)
如果您需要协议扩展中声明的方法,只需使编译器认为该汽车的类型为Vehicle
:
let myCar = Car()
(myCar as Vehicle).Stop()
答案 2 :(得分:0)
正如答案中已经提到的那样,通用解决方案是确保调用Stop()
方法的实例的类型为Vehicle
(而不是Car
)。不过,我要提一下背后的逻辑是什么。
我个人认为,在使用POP范式时,有可能会遇到此问题。协议扩展是在我们的代码中应用 Polymorphism 的便捷方式,但是确实会导致这种“怪异”的行为!
首先,请记住,它不是错误。在以下情况下:
let honda: Vehicle = Car()
honda.Drive()
honda.Stop()
有一个手动转换为honda
的{{1}},此时编译器将使用 static dispatch 表示可以识别在编译期间应调用哪个方法(Vehicle
或Vehicle().Stop
)。它为扩展中实现的Car().Stop
选择默认实现,而无需检查具体类型。
在以下情况下
:Vehicle
这里没有什么特别的,它完全按预期工作。这正是 dynamic dispatch 的含义,这导致在运行时应用 polymorphic 操作。
为更清楚起见,请考虑您使用另一种符合let myCar = Car()
myCar.Drive()
myCar.Stop()
协议的类型:
Vehicle
很明显,struct Bus: Vehicle {
func Drive() {
print("Bus Drive")
}
func Stop() {
print("Bus stop")
}
}
let myBus = Bus()
myCar.Drive()
myCar.Stop()
是将被调用的那个,实际上这是预期的!编译器“很聪明”,足以根据具体的类型(print("Bus stop")
)识别要选择的方法。
此外:
为更好地了解此处发生的情况,回顾Understanding Swift Performance Apple会议可能会有所帮助。
答案 3 :(得分:0)
您需要一个带有默认实现的协议,该协议允许一个结构参数,并且可以执行自定义行为:
import UIKit
struct Car{
//Any properties
func drive(){
print("Yo Drive")
}
func stop(){
print("Yo Stop")
}
}
protocol Vehicle {
func drive(vehicle : Car?)
func stop(vehicle : Car?)
}
extension Vehicle where Self: UIViewController {
func drive(vehicle : Car? = nil) {
if (vehicle != nil){
vehicle?.drive()
}else{
print("drive default behavior")
}
}
func stop(vehicle : Car? = nil) {
if (vehicle != nil){
vehicle?.stop()
}else{
print("stop default behavior")
}
}
}
class ViewController : UIViewController, Vehicle {
func driving() {
drive() //will print drive default behavior
stop() //will print stop default behavior
let car = Car()
drive(vehicle: car) //will print yo drive!
stop(vehicle: car) //will print yo Stop!
}
override func viewDidLoad() {
driving()
}
}