2016-11-27 11 views
0

で測定値を使用して、関数呼び出しでジェネリックを使用しないことの例です:どのように私は以下スウィフト3のいずれかの測定の値で動作する機能を必要としスウィフト3

機能の必要性を何
var test2 = Measurement<UnitEnergy>(value: 10.1234, unit: .calories) 

func printMeasurementGeneric(measurement: Measurement<Unit>) { 
    print(measurement.value) 
} 

func printMeasurementEnergy(measurement: Measurement<UnitEnergy>) { 
    print(measurement.value) 
} 

printMeasurementEnergy(measurement: test2) // This works 
printMeasurementGeneric(measurement: test2) // This doesn't work and give the following error 

Playground execution failed: error: Measurement Playground.playground:136:38: error: cannot convert value of type 'Measurement<UnitEnergy>' to expected argument type 'Measurement<Unit>' 
printMeasurementGeneric(measurement: test2) 

これが機能するにはPrintMeasurementGenericのように見えますか?

私はいくつかの進歩を遂げ、今、私は測定を保持するために、NSControlでobjectValueを使用しようとしている

var test = Measurement<UnitEnergy>(value: 10.1234, unit: .calories) 

func printMeasurementGeneric<A:Dimension>(measurement: Measurement<A>) { 
    print(measurement.value) 
} 

// This works 
printMeasurementGeneric(measurement: test) // This works 

// The following doesn't work 
var objectValue: Any? 
objectValue = test 

var meas = objectValue as! Measurement<Dimension> // Could not cast value of type 'Foundation.Measurement<NSUnitEnergy>' (0x11d324028) to 'Foundation.Measurement<NSDimension>' (0x11d324088). 
printMeasurementGeneric(measurement: meas) 

スウィフトの遊び場に次のコードを持っていました。すべての測定タイプにキャストできるかどうかをチェックするにはどうすればよいですか?

さらにいくつかの作業があり、以下の編集が含まれます。かなりか堅牢なソリューションではありません。

var test = Measurement<UnitEnergy>(value: 10.1234, unit: .calories) 

func printMeasurementGeneric<A>(measurement: Measurement<A>) { 
    print(measurement.value) 
} 

// This works 
printMeasurementGeneric(measurement: test) // This works 

// The following works but isn't pretty. Is there a better way 
var objectValue: Any? 
objectValue = test 

if objectValue is Measurement<UnitFrequency> { 
    let meas = objectValue as! Measurement<UnitFrequency> 
    printMeasurementGeneric(measurement: meas) 
} else if objectValue is Measurement<UnitLength> { 
    let meas = objectValue as! Measurement<UnitLength> 
    printMeasurementGeneric(measurement: meas) 
} else if objectValue is Measurement<UnitSpeed> { 
    let meas = objectValue as! Measurement<UnitSpeed> 
    printMeasurementGeneric(measurement: meas) 
} else if objectValue is Measurement<UnitEnergy> { 
    let meas = objectValue as! Measurement<UnitEnergy> 
    printMeasurementGeneric(measurement: meas) 
} else { 
    print("Didn't find cast!") 
} 
+0

ステップ1は、大文字で関数名を始めるこの習慣を停止することです。ただそれをやめてください。今。ありがとう。 – matt

+0

大文字を修正しました。 objectValueから測定値を取得するステップ2はNSControlですか? – Andrew

答えて

1

PrintMeasurementGenericの機能をこれに変更します。

func PrintMeasurementGeneric<Dimension>(measurement: Measurement<Dimension>) { 
    print(measurement.value) 
} 

私はDimensionタイプの代わりUnitを使用。いずれも機能しますが、すべての測定タイプはDimension(抽象サブクラスUnit)に準拠しています。

ハミッシュ(以下)が正しいです。

+0

ここにはちょっと混乱があります。「」は 'Dimension'という新しいジェネリックプレースホルダを導入していますが、' Foundation'の 'Dimension'クラスとはまったく関係ありません。あなたは先に進んでジェネリックプレースホルダ'フーバー(FooBar)」となり、違いはありません。また、 "Dimension"と "Unit"はプロトコルであると言って間違っています* " - 実際にはクラスです。キャストが機能しない理由は、ジェネリックが不変であるためです。 – Hamish

0

これは、プロトコルを用いて達成することができる。

protocol HasValue { 
    var value: Double { get set } 
} 
extension Measurement: HasValue { } 

func printValue<T: HasValue>(of item: T) { 
    print(item.value) // prints "10.1234" 
} 


var test = Measurement<UnitEnergy>(value: 10.1234, unit: .calories) 
printValue(of: test) 

printValueと同様の任意の機能を総称任意の測定を使用することができなければなりません。組織のためのプロトコル拡張に関数を含めることができます。

関連する問題