[解決済み] 関数のパラメータとしてクラス型を渡す方法
質問内容
ウェブサービスを呼び出し、JSONレスポンスをオブジェクトに戻す汎用関数があります。
class func invokeService<T>(service: String, withParams params: Dictionary<String, String>, returningClass: AnyClass, completionHandler handler: ((T) -> ())) {
/* Construct the URL, call the service and parse the response */
}
私が達成しようとしているのは、次のJavaコードに相当するものです。
public <T> T invokeService(final String serviceURLSuffix, final Map<String, String> params,
final Class<T> classTypeToReturn) {
}
- 私が達成しようとしていることに対するメソッドのシグネチャは正しいですか?
-
具体的には
AnyClass
をパラメータ型として使用することは というのが正しいのでしょうか? -
メソッドを呼び出すときに
MyObject.self
をreturnClassの値として使用しますが、コンパイル時に error "式の型 '()' を 'String'"' 型に変換できません。
CastDAO.invokeService("test", withParams: ["test" : "test"], returningClass: CityInfo.self) { cityInfo in /*...*/
}
編集する
を使ってみました。
object_getClass
, holexさんのおっしゃるとおりですが、今は、こうなります。
error: "Type 'CityInfo.Type' does not conform to protocol 'AnyObject'"
プロトコルに準拠するために必要なことは何ですか?
class CityInfo : NSObject {
var cityName: String?
var regionCode: String?
var regionName: String?
}
解決方法は?
Swiftでは、Objective-Cとは異なり、クラスは特定の型を持ち、さらに継承の階層を持ちます(つまり、もしクラス
B
を継承しています。
A
であれば
B.Type
も継承しています。
A.Type
):
class A {}
class B: A {}
class C {}
// B inherits from A
let object: A = B()
// B.Type also inherits from A.Type
let type: A.Type = B.self
// Error: 'C' is not a subtype of 'A'
let type2: A.Type = C.self
だから
AnyClass
を本当に許可したいのでなければ
任意の
クラスがあります。この場合、正しい型は
T.Type
の間のリンクを表現しているからです。
returningClass
パラメータとクロージャのパラメータを比較する。
実際、これを
AnyClass
を使用すると、コンパイラがメソッド呼び出しの型を正しく推測することができます。
class func invokeService<T>(service: String, withParams params: Dictionary<String, String>, returningClass: T.Type, completionHandler handler: ((T) -> ())) {
// The compiler correctly infers that T is the class of the instances of returningClass
handler(returningClass())
}
のインスタンスを作成する問題があります。
T
に渡すために
handler
今このコードを実行しようとすると、コンパイラーは
T
で構成することはできません。
()
. そして当然ながら
T
は、特定のイニシャライザーを実装するよう、明示的に制約を加える必要があります。
これは、以下のようなプロトコルで実現できます。
protocol Initable {
init()
}
class CityInfo : NSObject, Initable {
var cityName: String?
var regionCode: String?
var regionName: String?
// Nothing to change here, CityInfo already implements init()
}
の汎用制約を変更するだけです。
invokeService
から
<T>
から
<T: Initable>
.
チップ
式の型 '()' を 'String' 型に変換できない "のような奇妙なエラーが発生した場合、メソッド呼び出しのすべての引数を独自の変数に移動させると便利なことがよくあります。これは、エラーの原因となっているコードを絞り込み、型推論の問題を明らかにするのに役立ちます。
let service = "test"
let params = ["test" : "test"]
let returningClass = CityInfo.self
CastDAO.invokeService(service, withParams: params, returningClass: returningClass) { cityInfo in /*...*/
}
エラーが変数のひとつに移動するか(これは間違った部分がそこにあることを意味します)、あるいは "式の型を変換できません、というような不可解なメッセージが表示されるかのどちらかです。
()
をタイプ
($T6) -> ($T6) -> $T5
となります。
後者のエラーの原因は、書いたものの型をコンパイラが推論できていないことです。この場合、問題は
T
はクロージャのパラメータにしか使われておらず、渡されたクロージャは特定の型を示さないので、コンパイラはどの型を推論すればいいのかわからない。の型を変更することで
returningClass
を含めるようにしました。
T
を指定すると、コンパイラがジェネリックパラメータを決定するための方法を提供します。
関連
-
[解決済み] テスト
-
[解決済み] 使用しているSwiftのバージョンを確認するにはどうすればよいですか?
-
[解決済み] List<T>をオブジェクトのプロパティでソートする方法
-
[解決済み] リフレクションを使ってジェネリックメソッドを呼び出すにはどうしたらいいですか?
-
[解決済み] 汎用型Tのクラスインスタンスを取得する方法を教えてください。
-
[解決済み] 汎用クラスやメソッドのメンバからTの型を取得する方法
-
[解決済み] メソッドの戻り値の型を汎用的にするにはどうすればよいですか?
-
[解決済み] 純粋な」Swift で弱いプロトコル参照を作るには (@objc なしで) どうしたらいいですか?
-
[解決済み】なぜ、Swiftの文字列では、?のような絵文字が奇妙に扱われるのですか?
-
[解決済み] Swiftでカスタムメッセージを持つエラー/例外をスローする最も簡単な方法?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Swiftでbase64StringをStringに変換する方法とは?
-
[解決済み] Error: this class is not key value coding-compliant for key tableView.' [重複] を修正する方法。
-
[解決済み] なぜswiftではアンダースコアが必要なのですか?
-
[解決済み] 純粋な」Swift で弱いプロトコル参照を作るには (@objc なしで) どうしたらいいですか?
-
[解決済み] なぜクラスではなくストラクチャーを選ぶのか?
-
[解決済み】Swiftで変数の型またはクラスを表示するにはどうすればよいですか?
-
[解決済み】Swift 4でStringのsubstringを使うには?'substring(to:)'は非推奨です。部分的な範囲から'演算子を持つ文字列スライス添字を使用してください。
-
[解決済み】Xcode 6 Beta 4でアプリを実行すると「表示権限がないため、ファイル "MyApp.app" を開くことができません。
-
[解決済み】プログラムによってナビゲーションのタイトルを変更する
-
[解決済み】Swiftのenumのカウントを取得する方法は?