2016-09-25 3 views
2

私は静的に型付けされた言語を使い慣れていて、適切な多重定義された関数を呼び出すために構造体を型にキャストすることが可能かどうか疑問に思っていましたか?私が取り組んでいる問題は、Mutationプロトコルに準拠したStructsのリストです。私はリストを反復して、それぞれの構造体に対して正しいhandle関数を呼びたいと思います。私は、構造体自体にこのhandle機能を移動することもできますが、私が実装しようとしているAPIのために、私は以下のようにそのようなことが可能であるかどうかを確認したいと思います:あなたが好きなあなたのhandle()の機能を組み合わせることができ異なる構造のオーバーロード関数同じプロトコルを実装していますか?

//: Playground - noun: a place where people can play 

import UIKit 

protocol Mutation { 
    func mutate(state: Int) -> Int 
} 

struct CountIncrement: Mutation { 
    func mutate(state: Int) -> Int { 
     return state + 1 
    } 
} 

struct CountDecrement: Mutation { 
    func mutate(state: Int) -> Int { 
     return state - 1 
    } 
} 

func handle(mutation: CountIncrement, state: Int) -> Int { 
    print("WILL INCREMENT") 
    return mutation.mutate(state: state) 
} 

func handle(mutation: CountDecrement, state: Int) -> Int { 
    print("WILL DECREMENT") 
    return mutation.mutate(state: state) 
} 

var state = 0 
var queue = [CountIncrement(), CountDecrement()] as [Mutation] 

for mutation in queue { 
    handle(mutation: mutation, state: state) // error: cannot invoke 'handle' with an argument list of type '(mutation: Mutation, state: Int)' 
} 

答えて

1

これは、どのように問題に近づくべきかを示しています。 Swiftでは、フリー関数(例えばhandle(mutation:state:)など)を避け、型にメソッドを追加するのが一般的です。

ループには特定の方法が必要なので、新しいプロトコルが必要です(もちろんこの機能をMutationに追加することもできますが、別のアクセス制御などがある可能性があります。無料機能)。

protocol MutationHandling { 
    func handleMutation(forState state: Int) -> Int 
} 

私たちはあなたが望むこの機能は事だと宣言しました。今私たちが気にすることにそれを付けることができます。これは上記の自由な関数の記述とまったく同じです。それは同じパターンです。構文はまったく異なり、この関数が存在する理由についての追加のドキュメントを提供し、IDEが自動補完を提供してドキュメントをより効果的にまとめられるようにします。

var queue = [CountIncrement(), CountDecrement()] as [MutationHandling] 

をし、それを呼び出す:

extension CountIncrement: MutationHandling { 
    func handleMutation(forState state: Int) -> Int { 
     print("WILL INCREMENT") 
     return mutate(state: state) 
    } 
} 

は今、あなたはあなたのリストのために、この特別なプロトコルを使用

for mutation in queue { 
    mutation.handleMutation(forState: state) 
} 

これはスウィフトでちょうどいくつかのランダムな制限ではありません。これは、スウィフトが問題をどのように分解するかの深い部分です。フリー関数は明示的には避けてください(API Design Guidelines参照)。メソッドと拡張は、迅速な方法です。

1

このパラメータmutationのためにあなたのプロトコルMutationに準拠するすべてのオブジェクトを受け入れる:

func handle(mutation: Mutation, state: Int) -> Int { 
    return mutation.mutate(state: state) 
} 

この理由:

queueは、タイプが[Mutating]です。そのため、あなたのfor-LoopのmutationMutationになります。現在のところ、をパラメータとして受け取るhandle()関数はありません。

関連する問題