3

In java you can declare an interface like this

public interface Foo<T>
{
    public void doFoo(T result);
}

And you can use this as a type parameter in another method like this

public void doSomeAsyncTask(final Foo<MyObject> foo)
{
    Runnable asyncRunnable = new Runnable()
    {
        @Override
        void run()
        {
            MyObject result;
            // do task to get result
            foo.doFoo(result);
        }
    };
    Thread asyncThread = new Thread(asyncRunnable);
    asyncThread.start();
}

foo.doFoo(result);
}

As you can see I used the interface for callback from some asynchronous task that runs on a different thread.

UPDATE

Following this guide, I have come up with a solution similar to this

public protocol GenericProtocol {
    associatedType T
    func magic(result:T)
}

class GenericProtocolThunk<T> : GenericProtocol {
    private let _magic : (T)

    init<P : GenericProtocol where P.T == T>(_dep : P) {
        _magic = p.magic
    }

    func magic(result: T) {
        _magic(result)
    }
}

Now in my doSomeAsyncTask method I can just pass GenericProtocolThunk<MyObject> as the parameter type. Is this the right way to achieve what I asked in the question? Honestly it looks quite ugly to me.

Bhargav
  • 8,118
  • 6
  • 40
  • 63
  • have a look here: http://stackoverflow.com/questions/26401778/in-swift-how-can-i-declare-a-variable-of-a-specific-type-that-conforms-to-one-o?rq=1 – tgyhlsb Apr 29 '16 at 11:53
  • What is your question? Also, your code does not compile because of the misplaced `foo.doFoo(result)` call. – Clashsoft Apr 29 '16 at 12:05

2 Answers2

2

I think your problem boils indeed down to what is also noted in the blog post you link to:

"Protocols in Swift can be generic via abstract type members rather than parameterisation. Consequently, the protocol itself can no longer be used as a type but only as a generic constraint."

The (ugly) thunk based workaround looks like it solves your problem indeed, although to verify it would help if in your question you used similar terminology for both your Java and Swift examples, and they would be complete, including the type that actually contains the doSomeAsyncTask method to avoid possible confusions.

I can think of a few alternative more Swift friendly solutions if you can change the formulation a bit.

If you could describe Result too with a protocol, then the language isn't fighting against you quite so much. Compared to Java, conforming to a protocol (= implementing an interface) is also not limited to just class types, as shown in the below example so arguably you get a bit more rather out of the language to this end, than in Java:

import Foundation

protocol Result {
    // any restrictions on Result that you need.
}

class A:Result { }
struct B:Result { }
enum C:Result { case X }

protocol Foo {
    func doFoo(result:Result) -> Void
}

class Bar {
    func doSomeAsyncTask(foo:Foo) -> Void {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            foo.doFoo(A())
            foo.doFoo(B())
            foo.doFoo(C.X)
        }
    }
}

Another alternative that I've used only recently myself in a related sort of problem is to model result as an enum which enumerates the possible result types, like below (incidentally, each of BibliographyItem, InlineMathFragment, Equation, BlockElement, InlineElement in my code example below are themselves protocols, not concrete types):

public enum Result {
    case None
    case BibliographyItems([BibliographyItem])
    case InlineMathFragments([InlineMathFragment])
    case Equations([Equation])
    case BlockElements([BlockElement])
    case InlineElements([InlineElement])
}

This is handy in a situation where your results come from some already known set of result types, and you commonly end up needing to deal with them in some conditional form.

mz2
  • 4,672
  • 1
  • 27
  • 47
1

You may want to simplify it to:

func doSomeAsyncTask<T>(callback: (T)->Void)

Check out this great video:

Rob Napier: Beyond Crusty: Real world protocols

Mike Pollard
  • 10,195
  • 2
  • 37
  • 46