2017-01-05 3 views
0

タイプAny?の変数を保持/取得するジェネリッククラスを宣言したいが、要求時にこの変数を指定の型にキャストする。このo.value(forKeyPath: k)nilTときになるように、私は仕事にこれにたいジェネリック型のゼロを生成する方法

class A<T> { 
    var o: NSObject! 
    var k: String! 
    var v: T { 
     get { return o.value(forKeyPath: k) as! T } 
     set { o.setValue(newValue, forKeyPath: k) } 
    } 
} 

nilを保持することができます(それがExpressibleByNilLiteralである)、(タイプTの)v戻りnilような何か。それは、as!のためにクラッシュします。これは可能ですか?

この時試みた亀裂は、この( How to make a computed property of a generic class depend on the class constraintsによって提案された)

class A<T> { 
    var o: NSObject! 
    var k: String! 
    var v: T { 
     get { 
      let x = o.value(forKeyPath: k) 
      if let E = T.self as? ExpressibleByNilLiteral.Type { 
       if let x = x { return x as! T } 
       let n: T = <nil of type T> <---- not sure what to put here 
       return n 
      } else { 
       return x as! T 
      } 
     } 
     set { o.setValue(newValue, forKeyPath: k) } 
    } 
} 

のように見えますが、私はそれを動作させる方法がわからないです。

+0

有効なT(ExpressibleByNilLiteralに準拠)がどのように見えるかを表示できますか? –

+0

ドキュメントでは、「nilはSwiftで特定の意味を持っています。値がない場合、Optional型だけがExpressibleByNilLiteralに準拠します。他の目的でnilを使用する型のExpressibleByNilLiteral適合は推奨されません。 –

+0

正しい(任意の) 'Optional'型は' ExpressibleByNilLiteral'に従います。 'init(nilLiteral:())'だけを必要とし、 'let n:T = E.init(nilLiteral:())を!と書くことができます。 (オプションのソースコードのコメントはこれを止めているようだが)。残念ながら、 'E.init(nilLiteral:())'は...であるため、これはクラッシュします。 'nil'と' as! 'は失敗します。これは、呼び出すことのできる何らかの種類の 'init'を提供するプロトコルで動作します。しかし、 'as! 'の実装は' 'ExpressibleByNilLiteral''と"エンタングル "されており、問題はそれらをどのように分けるかです。 – user3763801

答えて

1

なぜわからないが、これは実際に私たちはしたくない場合に、今私たちはcastですべてas!呼び出しを置き換えることができ、とにかく...私はすでにこれを試み、それがうまくいかなかったと思っ

func cast<T>(_ v: Any?)->T { 
    if let E = T.self as? ExpressibleByNilLiteral.Type { 
     if let v = v { 
      return v as! T 
     } else { 
      return E.init(nilLiteral:()) as! T 
     } 
    } else { 
     return v as! T 
    } 
} 

の作品nilにクラッシュします。キャストしようとしているタイプがそれを取ることができます。私の質問のゲッターで。

関連する問題