Search code examples
swiftpropertiesblocksubclassing

Extract self-properties in block-method


I have some trouble in understanding my specific request, in Swift. There is a class named Origin and multiple its subclasses. How I can update my block-method written ONLY in Origin class?

class Origin: NSObject {
    func mod(_ block: (() throws -> Void)) {
        try! block()
    } 
}

I need use mod from all Origin subclasses, and I need to have this usage effect:

var originSubclassObject = OriginSubclass() 
originSubclassObject.mod {
    .age = 12 //age is OriginSubclass property
    .name = "Bob" //name is OriginSubclass property
}

So, you see, I need extract OriginSubclass properties for using in mod-block. I need to create usage exactly likes in usage effect code (extract mod-caller properties from "."). Thanks all for help!


Solution

  • You could consider a protocol with a default implementation, e.g.:

    protocol Modifiable { }
    
    extension Modifiable {
        func mod(_ block: ((Self) throws -> Void)) {
            try! block(self)
        }
    }
    
    class Origin: Modifiable { }
    
    class OriginSubclass: Origin {
        var name: String?
        var age: Int?
    }
    

    And then:

    let originSubclassObject = OriginSubclass()
    originSubclassObject.mod { object in
        object.age = 12
        object.name = "Bob"
    }
    

    Or

    let originSubclassObject = OriginSubclass()
    originSubclassObject.mod {
        $0.age = 12
        $0.name = "Bob"
    }
    

    Or, if that base class was only there for the mod method, you could lose it entirely:

    protocol Modifiable { }
    
    extension Modifiable {
        func mod(_ block: ((Self) throws -> Void)) {
            try! block(self)
        }
    }
    
    class MyObject: Modifiable {
        var name: String?
        var age: Int?
    }
    

    And

    let myObject = MyObject()
    myObject.mod { object in
        object.age = 12
        object.name = "Bob"
    }
    

    Or

    let myObject = MyObject()
    myObject.mod {
        $0.age = 12
        $0.name = "Bob"
    }