2017-06-04 14 views
0

クラスclass C<T>があるとします。オブジェクトがジェネリッククラスを継承するか、またはジェネリッククラスのメンバーであるかどうかをテストするにはどうすればよいですか?

私はaC(又はC自体である)から継承するクラスのメンバーである場合に真を返す関数f(_ a: Any) -> Boolを書きたいです。私は専門化を気にしません:C<Int>C<Double>C<Whatever>をすべて返すのはtrueです。

それは、私はちょうどその関数の本体としてa is Cまたはa as? C != nilを書くことができるはずのように思える、しかし、これらの両方の遊び場にコンパイルされません。 swiftcは「C < _>」へのキャストで「ジェネリックパラメータ「T」」を推論できないと訴えています。インスタンスメソッドとしてCの中にfを書き込むと、Cは暗黙的にC<T>であるため、let c = C<Int>(); c.f(C<Double>())を書き込むとfalseが返されます。

PCが準拠しているプロトコルを作成して対処することができますが、それをテストしますが、それは良い解決策ではありません。それはちょうどハックです。

これを行う方法はありますか?それはちょうど、オブジェクトがのサブクラスであることを知っておくと便利ではないので、私は、あなたがこれを行うにするために言語機能が存在するとは思わない

class C<T> { 
    func test(_ a: Any) -> (Bool, Bool) { 
    return (type(of: a) == C.self, a is C) 
    } 
} 

class D: C<Double> { } 

let d = D() 

func f(_ a: Any) -> Bool { 
    return a is C // generic parameter 'T' could not be inferred in cast to 'C<_>' 
} 

d.test(C<Int>()) // false, false 

// bad solution 

protocol P { } 

extension C: P { } 

d is P // true 

答えて

0

:ここ

は、私はこれを試して書いたすべてのコードです、またはCそのもので、ジェネリック型パラメータを知らなくても可能です。

つまり、someObjは実際にタイプC<Something>であることを知った後に何をするつもりですか?Somethingは何ですか? someObjectで何もできません。キャストすることはできませんので、メンバーにアクセスすることはできません。あなたはこれをしたいと主張した場合

スウィフトのジェネリック医薬品が...ただ、実行時に窓の外にジェネリック型をスローするJavaとは異なり、

非常に非常に厳格で、あなたの唯一のオプションは使用することですあなたが言ったハック

それとも、あなただけのaC自体ではなく、そのサブクラスのいずれかであるかどうかを確認したい場合は、(楽しみのためだけに)これを使用することができます:

func f(a: Any) -> Bool { 
    let regex = try! NSRegularExpression(pattern: "C<.+>") 
    let typeString = String(describing: type(of: a)) 
    let range = NSRange(location: 0, length: typeString.characters.count) 
    let matchRange = regex.rangeOfFirstMatch(in: typeString, range: range) 
    return range.toRange() == matchRange.toRange() 
} 
+0

有用性についてご説明します。 'someObject'が特殊化されている型がわからないからといって、' C'から継承した知識が役に立たないということを意味するわけではありません。あるオブジェクト(例えば、ビュー階層内のスーパービュー)がタイプCであることを知っているだけで、その下のビューに関する一定の不変条件が成り立つことを意味するかもしれません。 –

+0

@BenPiousビューの階層構造の場合は、 'tag'を使用してください。スーパービューのタグが何らかの値であるかどうかを調べることで、それがあなたが探しているビューかどうかを知ることができます。彼らは十分ではありませんか? – Sweeper

+0

誰かが私がいくつかのビューのためにしたのと同じタグを選ぶことができました。さらに、 'C 'のユーザは、' C'から継承する型のインスタンスのタグを設定できないことを知る必要があります。あるいは、 'C'の実装の詳細を破ることになります。明らかにするために、 'C'のメンバーであることは、不変量が成り立つことを知るのに十分です。それは特定の例ではありません。だから私はそれをテストできるようにしたい。私が質問の最後に言ったように、 'C'(そして' C'のみ)に従う 'P'でジェネリックを消去しないと、私はそれをすることができないようです。 –

0

はダンプが

func dump<T, TargetStream where TargetStream : TextOutputStream>(_ value: T, to target: inout TargetStream, name: String? = default, indent: Int = default, maxDepth: Int = default, maxItems: Int = default) -> T 
宣言されている方法を参照してください。

そして、それは

class C<T>{} 
class D:C<Double>{} 

let c = C<Void>() 
let d = D() 

dump(c) 
dump(d) 

はい、ダンプを生成しますかどうか確認しますSwiftの標準ライブラリの一部です...反射(オブジェクトミラー)を使用して結果を生成します。

UPDATE

私は1つのファイルのメインとdumptestという名前のCLIのプロジェクトを作成しました。

import Cocoa 

let v = NSView() 
dump(v) 

ダンプ値を持つことができます迅速

それはプログラムがstackoverflowのを確認するか、新しい質問をするString型の変数を解析するために

type info about c: - dumptest.C<()> #0 

type info about d: - dumptest.D #0 
    - super: dumptest.C<Swift.Double> 

type info about e: - dumptest.E #0 
    - super: dumptest.D 
    - super: dumptest.C<Swift.Double> 

Program ended with exit code: 0 

を報告し実行している

// 
// main.swift 
// dumptest 
// 

class C<T>{} 
class D:C<Double>{} 
class E:D{} 

let c = C<Void>() 
let d = D() 
let e = E() 

var tc = "" 
var td = "" 
var te = "" 

dump(c, to: &tc) 
dump(d, to: &td) 
dump(e, to: &te) 

print("type info about c:", tc) 
print("type info about d:", td) 
print("type info about e:", te) 

... vとあります。

- <NSView: 0x100a022a0> #0 
    - super: NSResponder 
    - super: NSObject 
Program ended with exit code: 0 

あなたは「より複雑な」何かが必要な場合は、あなたがこのテストに期待していると、すべてのハックではなく、指定したプロトコルを書く Mirror

+0

申し訳ありませんが、私はこれがどのように質問に答えるかはわかりません。 'f'関数の実装が' dump'にどのように関連しているのか少し詳しく説明できますか? – Sweeper

+0

@Sweeper dumpは、ミラーリングを迅速に使用する最も簡単な方法です。スニペットを実行すると、その結果が人間が判読可能な形式で表示され、OPが探しているものを簡単に認識できることがわかります。結果をコンピューターで読むことができるコード行はほとんどありません:-) – user3441734

+0

'dump'は標準出力に出力します。実行時にこれをテストしたい場合は実際には役に立たない。それはあなたに解析する文字列を与えなかったとしても、それは 'ダンプ(d)のための出力である「_TtGC14__lldb_expr_281CSi_を」、デマングルする方法は全く私には明らかではありません' –

0

で遊ぶことができます。スウィフトをどのように使うべきかはまさにそれです。 (あなたが求めていることは、本当に不可能であり、意図的にそうです。)そのプロトコルを書いてください。空のハックではありません。あなたがテストしようとしているものを記入し、それをあなたのコードの構造の美しい部分として見てください!

関連する問題