web-dev-qa-db-ja.com

swiftの匿名クラス

Swiftの匿名クラスに同等の構文またはテクニックはありますか?わかりやすくするためにJavaの例はこちら)- http://docs.Oracle.com/javase/tutorial/Java/javaOO/anonymousclasses.html

ありがとう!

32
eranh

私の知る限り、同等の構文はありません。

同等の手法に関しては、理論的にはクロージャーを使用して、その内部に構造体とクラスを定義できます。悲しいことに、私はこれをプレイグラウンドやプロジェクトでクラッシュさせることなく動作させることはできません。ほとんどの場合、これは現在のベータ版で使用する準備ができていません。

何かのようなもの...

protocol SomeProtocol {
    func hello()
}

let closure : () -> () = {
    class NotSoAnonymousClass : SomeProtocol {
        func hello() {
            println("Hello")
        }
    }
    let object = NotSoAnonymousClass()
    object.hello()
}

...現在このエラーを出力します:

invalid linkage type for global declaration
%Swift.full_heapmetadata* @_TMdCFIv4Test7closureFT_T_iU_FT_T_L_19NotSoAnonymousClass
LLVM ERROR: Broken module found, compilation aborted!
Command /Applications/Xcode6-Beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/Swift failed with exit code 1
14
hpique

また、ベアプロトコルのように機能する基本的な空のクラスを作成し、次のように、必要なものをオーバーライドするinit関数にクロージャーを渡すこともできます。

class EmptyClass {

    var someFunc: () -> () = { }

    init(overrides: EmptyClass -> EmptyClass) {
        overrides(self)
    }
}

// Now you initialize 'EmptyClass' with a closure that sets
// whatever variable properties you want to override:

let workingClass = EmptyClass { ec in
    ec.someFunc = { println("It worked!") }
    return ec
}

workingClass.someFunc()  // Outputs: "It worked!"

技術的には「匿名」ではありませんが、同じように機能します。クラスの空のシェルが与えられ、それをクロージャーで初期化するときに、それを埋めるか、必要なパラメーターをオーバーライドします。

基本的には同じですが、プロトコルの期待を満たす代わりに、クラスのプロパティをオーバーライドします。

11
Aaron Rasmussen

たとえば、Java listener/adapterパターンはSwiftのように変換されます。

protocol EventListener {
    func handleEvent(event: Int) -> ()
}

class Adapter : EventListener {
    func handleEvent(event: Int) -> () {
    }
}

var instance: EventListener = {
    class NotSoAnonymous : Adapter {
        override func handleEvent(event: Int) {
            println("Event: \(event)")
        }
    }

    return NotSoAnonymous()
}()

instance.handleEvent(10)

(ベータ2でのコンパイラのクラッシュ)

問題は、常に名前を指定する必要があることです。 Appleが匿名クラス(および構造体など)を導入することはないだろうと思う。

また、プログラミングでは匿名のものが悪いです。物に名前を付けると、読者がコードを理解しやすくなります。

9
Sulthan

Swiftには匿名クラス構文はありません。ただし、クラスおよびクラスメソッド内にクラスを作成できます。

class ViewController: UIViewController {

    class anonymousSwiftClass {
        func add(number1:Int, number2:Int) -> Int {
            return number1+number2;
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        class innerSwiftClass {
            func sub(number1:Int, number2:Int) -> Int {
                return number1-number2;
            }
        }

        var inner = innerSwiftClass();
        println(inner.sub(2, number2: 3));

        var anonymous = anonymousSwiftClass();
        println(anonymous.add(2, number2: 3));
    }
}
7

これが私がやったことです(Observerパターン)。 Javaで匿名クラスを使用するのと同様の方法でクロージャを使用できます。もちろん明らかな制限があります。

class Subject {
   // array of closures
   var observers: [() -> Void] = []

   // @escaping says the closure will be called after the method returns
   func register(observer: @escaping () -> Void) {
       observers.append(observer)
   }

   func triggerEvent() {
       observers.forEach { observer in
            observer()
       }
   }
}

var subj = Subject()
// you can use a trailing closure
subj.register() {
    print("observerd")
}

// or you can assign a closure to a variable so you can maybe use the reference to removeObserver() if you choose to implement that method
var namedObserver: () -> Void = {
    print("named observer")
}
subj.register(observer: namedObserver)

subj.triggerEvent()
// output:
// observerd
// named observer
0