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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With