簡體   English   中英

你如何在Swift中使用Java等效的Generic回調接口

[英]How do you do java equivalent of Generic callback interface in Swift

在java中,您可以聲明這樣的接口

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

你可以在另一個方法中使用它作為類型參數

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);
}

正如您所看到的,我使用接口從一個在不同線程上運行的異步任務進行回調。

UPDATE

按照本指南 ,我提出了類似的解決方案

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

現在在我的doSomeAsyncTask方法中,我可以將GenericProtocolThunk<MyObject>作為參數類型傳遞。 這是實現我在問題中提出的問題的正確方法嗎? 老實說,對我來說這看起來很難看。

我認為您的問題確實歸結為您鏈接到的博客文章中也提到的內容:

“Swift中的協議可以通過抽象類型成員而不是參數化來實現。因此,協議本身不能再用作類型,而只能用作通用約束。”

(丑陋的)基於thunk的解決方案看起來確實解決了你的問題,盡管如果在你的問題中你使用類似的Java和Swift示例的術語來驗證它會有所幫助,並且它們將是完整的,包括實際包含的類型doSomeAsyncTask方法可以避免可能的混淆。

如果你能稍微改變配方,我可以想到一些替代Swift友好的解決方案。

如果你也可以用協議來描述結果,那么語言就不會對你起作用了。 與Java相比,符合協議(=實現接口)也不僅限於類類型,如下面的示例所示,因此可以說,為了達到這個目的,您可以比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)
        }
    }
}

我最近才在相關類型的問題中使用的另一種替代方法是將結果建模為枚舉,枚舉可能的結果類型,如下所示(順便InlineElement ,我的代碼示例中的每個BibliographyItemInlineMathFragmentEquationBlockElementInlineElement下面是協議,而不是具體類型):

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

在您的結果來自一些已知的結果類型集合的情況下,這很方便,並且您通常最終需要以某種條件形式處理它們。

您可能希望將其簡化為:

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

看看這個精彩的視頻:

Rob Napier:超越硬殼:真實世界的協議

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM