Implementing a function with a default parameter defined in the protocol

Swift protocols can provide standard implementations of functions and computed properties by adding extensions to them. I have done this many times. I understand that the default implementation is only used as a “fallback” one . It is executed when the type conforms to the protocol but does not provide its own implementation.

At least as I read the Quick Programming Guide :

If the corresponding type provides its own implementation of the required method or property, this implementation will be used instead of the one provided by the extension.

Now I am faced with a situation where my user type, which implements a specific protocol, provides an implementation for a specific function, but does not execute - instead, the implementation defined in the protocol extension is executed.


As an example, I define a protocol Movablethat has a function move(to:)and an extension that provides a default implementation for this function:

protocol Movable {

    func move(to point: CGPoint)

}

extension Movable {

    func move(to point: CGPoint = CGPoint(x: 0, y: 0)) {
        print("Moving to origin: \(point)")
    }

}

Next, I define a class Carthat matches Movable, but provides its own implementation for the function move(to:):

class Car: Movable {

    func move(to point: CGPoint = CGPoint(x: 0, y: 0)) {
        print("Moving to point: \(point)")
    }

}

Now I create a new one Carand omit it as Movable:

let castedCar = Car() as Movable

Depending on whether I pass a value for an optional parameter point, I observe two different behaviors:


  • Car :

    castedCar.move(to: CGPoint(x: 20, y: 10)) 
    

    :

    : (20.0, 10.0)


  1. move() , Car

    Movable :

    castedCar.move()
    

    :

    : (0.0, 0.0)


?

+6
1

,

castedCar.move(to: CGPoint(x: 20, y: 10))

func move(to point: CGPoint) - - (, ), Car,

,

castedCar.move()

func move(to point: CGPoint). - ( ). , castedCar castedCar Movable, . .

- - ( ).

, , ( ), .

. - ., , .


, , , static move() , move(to:).

protocol Moveable {
    static var defaultMoveToPoint: CGPoint { get }
    func move(to point: CGPoint)
}

extension Moveable {

    static var defaultMoveToPoint: CGPoint {
        return .zero
    }

    // Apply move(to:) with our given defined default. Because defaultMoveToPoint is a 
    // protocol requirement, it can be dynamically dispatched to.
    func move() {
        move(to: type(of: self).defaultMoveToPoint)
    }

    func move(to point: CGPoint) {
        print("Moving to origin: \(point)")
    }
}

class Car: Moveable {

    static let defaultMoveToPoint = CGPoint(x: 1, y: 2)

    func move(to point: CGPoint) {
        print("Moving to point: \(point)")
    }

}

let castedCar: Moveable = Car()
castedCar.move(to: CGPoint(x: 20, y: 10)) // Moving to point: (20.0, 10.0)
castedCar.move() // Moving to point: (1.0, 2.0)

defaultMoveToPoint - , .

, defaultMoveToPoint type(of: self) Self. , , , defaultMoveToPoint defaultMoveToPoint. , - move() ( Moveable), Self.

, , .

+8

Source: https://habr.com/ru/post/1015538/


All Articles