swift program to interface

后端 未结 2 1836
故里飘歌
故里飘歌 2021-01-26 13:44

class Car and Truck are written here as an example but they could be unknown to the program at compile time.

there could be more kinds of cars not yet known

for

相关标签:
2条回答
  • 2021-01-26 14:19

    To be able to create a generic type generically, you need to know that it supports an initializer. You can do this by adding an init() function to the protocol:

    public protocol Drivable {
        // enable drivable things to be
        // created with a  default initializer
        init()
    
        // (you could instead require a type implement
        // an initializer that took parameters)
    
        func drive()
    }
    

    You can then write functions that create and operate on them generically:

    struct Car: Drivable {
        init() { }
        func drive() { println("vroom") }
    }
    
    struct Truck: Drivable {
        init() { }
        func drive() { println("brrrrrrm") }
    }
    
    struct Test<D: Drivable> {
        func instantiateAndDrive() {
            // whatever D is, it implements init()
            let d = D()
            // and drive()
            d.drive()
        }
    }
    
    Test<Car>().instantiateAndDrive()
    Test<Truck>().instantiateAndDrive()
    

    Though with this approach, when you say, “class Car and Truck are written here as an example but they could be unknown to the program at compile time” – the above code means they don’t need to be known to the implementation of Test at compile time. But they do need to be known to the caller of test at compile time.

    This approach is more useful when a genric function is returning a type. For example, ExtensibleCollectionType requires init() and so can be used like this:

    func returnCollectionContainingOne<C: ExtensibleCollectionType where C.Generator.Element == Int>() -> C {
    
        // this is allowed because the ExtensibleCollectionType procol 
        // requires the type implement an init() that takes no parameters
        var result = C()
    
        // and it also defines an `append` function that allows you to do this:
        result.append(1)
    
        // note, the reason it was possible to give a "1" as the argument to
        // append was because of the "where C.Generator.Element == Int" part
        // of the generic placeholder constraint 
    
        return result
    }
    
    // now you can use returnCollectionContainingOne with arrays:
    let a: [Int] = returnCollectionContainingOne()
    
    // or with ContiguousArrays:
    let b: ContiguousArray = returnCollectionContainingOne()
    
    0 讨论(0)
  • 2021-01-26 14:23

    You want to use Self. In a protocol, it means "the type that actually adopts me". In a method of a class, it means "the class in which this method is actually called".

    0 讨论(0)
提交回复
热议问题