SmT SmT - 10 days ago 4
Swift Question

Java interface equivalent in Swift


EDIT: What is different between What is the equivalent for java interfaces or objective c protocols in swift? and this question?


After I read that topic, I thought It was an option to use a class to extend the protocol, and I tried to create the protocol itself with no success, but as Duncan C. said it is not possible to initialise a protocol type directly and I have to extend it with another class.

My Problem: I have a class in Java, I hold an array of interfaces, that way I can loop through the array and call the doWork() function until one of them returns true. I want to achieve the same functionality in Swift.

My java class:

class MyClass{
//create a variable that holds all of my engines
private MyEngine[] myEngines = new MyEngine[]{
new MyEngine(){
@Override
public boolean doWork(){
return doWork1();
}
},
new MyEngine(){
@Override
public boolean doWork(){
return doWork2();
}
},
new MyEngine(){
@Override
public boolean doWork(){
return doWork3();
}
}
}

//loop through all engines until one of them succeed
public boolean doWorkUntilSuccess(){
for(int i = 0; i < myEngines.length; i++){
if(myEngines[i].doWork())
return true;
}
return false;
}

private boolean doWork1(){
//code
return result;
}

private boolean doWork2(){
//code
return result;
}

private boolean doWork3(){
//code
return result;
}

interface MyEngine{
boolean doWork();
}
}

Answer

The Swift equivalent to an interface is a Protocol, as Connor says in his answer.

Again, borrowing from Connor's answer:

protocol MyEngine {
    func doWork() -> Bool
}

You can't instantiate objets of type MyEngine directly. Instead you need to define one or more objects that conform to the protocol:

class Obj1: MyEngine {
    func doWork() -> Bool {
        print("in Obj1 doWork()")
        return true
    }
}

class Obj2: MyEngine {
    func doWork() -> Bool {
        print("in Obj2 doWork()")
        return true
    }
}

You can then define an array of objects that conform to the protocol:

var objArray = [MyEngine]()

Then populate the array:

objArray.append(Obj1())
objArray.append(Obj2())
objArray.append(Obj2())
objArray.append(Obj1())

You can then say

objArray.forEach{$0.doWork()}