快速程序接口 [英] swift program to interface

查看:117
本文介绍了快速程序接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

汽车和卡车类在这里写成一个例子,但编译时他们可能不知道该程序。



可能有更多种类的汽车尚未知道



例如,可能会有一个名为法拉利(Lamborghini)的特殊课程,可能会落在系统未知的道路上。



我们的目标是编程界面,而不是一个具体的实现



我们需要做类似以下的


  1. 创建一个实例 var vehicle:IDrive = Vehicle()

  2. vehicle.drive()

我们尝试了一些技巧,无法使其工作



任何侧面的方法也欢迎,也许我们的方法是完全错误的,但请牢记函数 instantiateAndDriv的约束e 必须有一个协议参数



而是提出问题来澄清是否对你没有意义,或者去自己一个Idiots的设计模式书

  public protocol IDrive {
func drive()
}

public class Car:IDrive {
public init(){}
public func drive(){}
}

class卡车:IDrive {
public init(){}
public func drive(){}
}

class Test {//我们的尝试
func instantiateAndDrive(Vehicle:IDrive.Type){
var vehicle = Vehicle()
vehicle.drive )

}

func instantiateAndDrive2< T:IDrive>(Vehicle:T){
var vehicle = Vehicle()
vehicle.drive
}
}

var test = Test()
test.instantiateAndDrive(Car.self)

编辑 - 尝试在AirSpeed Velocity的答案后使用课程

 公共协议Drivable {
init()
func drive()
}

public class Car:Drivable {
public required init(){}
public func drive(){println(vroom)}
}

public class卡车:Drivable {
public required init(){}

public func drive(){println(brrrrrrr)}
}

class Test {
func instantiateAndDrive(Vehicle:Drivable.Type){
var vehicle = Vehicle()
vehicle.drive()
}

func instantiateAndDrive2< T:Drivable>(Vehicle:T){
ver vehicle = Vehicle ()
vehicle.drive()
}
}
// var test = Test()
//test.instantiateAndDrive(Car.self)
// test.instantiateAndDrive(Truck.self)


解决方案

为了能够创建一个通用类型ge在神经上你需要知道它支持一个初始化器。您可以通过在协议中添加 init()函数来执行此操作:

  public protocol Drivable {
//启用可驱动的东西为
//使用默认初始化程序创建
init()

//(可以改为需要一个类型实现
//一个使用参数的初始化器

func drive()
}

然后,您可以编写一般地创建和操作的函数:

  struct Car :Drivable {
init(){}
func drive(){println(vroom)}
}

struct卡车:Drivable {
init(){}
func drive(){println(brrrrrrm)}
}

struct Test&D:Drivable> {
func instantiateAndDrive(){
//任何D,它实现init()
let d = D()
//和drive()
d .drive()
}
}

测试< Car>()。instantiateAndDrive()
测试< Truck>()。instantiateAndDrive()
尽管采用这种方法,但是当你说汽车和卡车这个作为一个例子写在这里,但是他们可能是未知的在编译时对程序 - 上面的代码意味着它们在编译时不需要被实现为Test。但是他们确实需要在编译时被测试的调用者知道。



当一个genic函数返回一个函数时,这种方法更有用类型。例如, ExtensibleCollectionType 需要 init(),因此可以这样使用:

  func returnCollectionContainingOne< C:ExtensibleCollectionType其中C.Generator.Element == Int>() - > C {

//这是允许的,因为ExtensibleCollectionType procol
//要求类型实现不需要参数的init()
var result = C()

//,它还定义了一个`append`函数,允许你这样做:
result.append(1)

//注意,可能的原因给出一个1作为参数
// append是因为where C.Generator.Element == Int部分
//通用占位符约束

return result
}

//现在您可以使用returnCollectionContainingOne与数组:
let a:[Int] = returnCollectionContainingOne()

/ /或ContiguousArrays:
let b:ContiguousArray = returnCollectionContainingOne()


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 instance there could be a special class called Ferrari, Lamborghini, that may come down the road not known to the system.

our objective is to program to interface, not to a specific implemenation

we need to do similar to the following

  1. create an instance var vehicle: IDrive = Vehicle()
  2. vehicle.drive()

we tried some techniques and couldn't get it working without casting to specific implementations, need an independent solution without a need to cast to a specific implementation.

Any lateral approach also welcome, maybe our approach is totally wrong but keeping in mind the constraints that function instantiateAndDrive has to have a protocol based parameter

Note to negative voters aka dummies: instead ask questions to clarify if it doesn't make sense to you or go get yourself a "Design Pattern Book for Idiots"

    public protocol IDrive {
        func drive()
    }

    public class Car: IDrive {
        public init() {}
        public func drive() {}
    }

    class Truck: IDrive {
        public init() {}
        public func drive() {}
    }

class Test { //our attempts
   func instantiateAndDrive(Vehicle:IDrive.Type) {
       var vehicle = Vehicle()
       vehicle.drive()

   }

    func instantiateAndDrive2<T:IDrive>(Vehicle: T) {
        var vehicle = Vehicle()
        vehicle.drive()
    }
}

var test = Test()
test.instantiateAndDrive(Car.self)

Edit - Attempt using class after AirSpeed Velocity's Answer

public protocol Drivable {
    init()
    func drive()
}

public class Car: Drivable {
    public required init() {}
    public func drive() { println("vroom") }
}

public class Truck: Drivable {
    public required init() {}

    public func drive() { println("brrrrrrm") }
}

class Test {
    func instantiateAndDrive(Vehicle:Drivable.Type) {
        var vehicle = Vehicle()
        vehicle.drive()
    }

    func instantiateAndDrive2<T:Drivable>(Vehicle: T) {
        ver vehicle = Vehicle()
        vehicle.drive()
    }
}
//var test = Test()
//test.instantiateAndDrive(Car.self)
//test.instantiateAndDrive(Truck.self)

解决方案

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()

这篇关于快速程序接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆