2014-10-24 20 views
6

ho a che fare con diverse unità, vale a dire distance, altitude, speed, volume, eccdell'estensione alias in rapida

Il mio obiettivo è quello di avere un modo unico elegante per formattarli in app, come ad esempio chiamando myValue.formatted:

let mySpeed: Speed = 180 
println(mySpeed.formatted) // 5.0 km/h 

let myAltitude: Altitude = 4000 
println(myAltitude.formatted) // 4000 m 

ho pensato che questo era un buon caso per l'utilizzo di tipo alias.

typealias Distance = Float 
typealias Altitude = Float 
typealias Speed = Float 

Per la proprietà formatted, ho provato con una extension del tipo Float:

extension Float { 
    var formatted: String { 
     get { 
      switch self { 
      case is Altitude: 
       return "\(self) m" 
      case is Speed: 
       return "\(self * 3.6) km/h" 
      default: 
       return "\(self)" 
      } 
     } 
    } 
} 

Ma il compilatore dice che il mio case blocchi sono sempre true.

Poi ho cercato di estendere il tipo singolo:

extension Speed { 
    var formatted: String { 
    return "\(self * 3.6) km/h" 
    } 
} 
extension Altitude { 
    var formatted: String { 
    return "\(self) m" 
    } 
} 

il compilatore ora afferma chiaramente ridichiarazione non valido di 'formattato'

OK, è chiaro ora come funzionano tipo alias. Ma come potrei ottenere la mia proprietà .formatted per diversi tipi di Float in swift?

risposta

5

typealias basta cambiare o rinominare il tipo. Non crea un altro tipo di utente per te. Attualmente stai estendendo di nuovo Float per Speed, Altitude.

È possibile passare 180 alla struttura personalizzata conformando i tipi Literals.

let mySpeed: Speed = 180 

FloatLiteralConvertible e IntegerLiteralConvertible vi darà stessa funzionalità che si desidera ed è possibile assegnare direttamente i valori per la vostra abitudine struct types come si assegna al Float

struct Speed: FloatLiteralConvertible,IntegerLiteralConvertible { 

    var distance:Float 
    init(floatLiteral value: Float) { 
     distance = value 
    } 

    init(integerLiteral value: Int){ 
     distance = Float(value) 
    } 

    var formatted: String { 
     return "\(distance * 3.6) km/h" 
    } 
} 

let mySpeed: Speed = 180.0 
println(mySpeed.formatted) // 5.0 km/h 
+0

Questo è davvero molto interessante. È un po 'deludente non posso lanciare un 'floatVar come Speed', cioè usando la parola chiave' as'. Il tipo alias era elegante in questo modo. – gpbl

+0

@crumblenaut hai ragione. La velocità ora non è 'Float'. È un tipo personalizzato definito dall'utente.Puoi 'format'' Float' con una funzione con un solo tipo. Se vuoi veramente farlo usa 'formatSpeed', formatDistance in extensions. – codester

1

Distance, Altitude, e Speed è sempre lo stesso tipo - Float e condividono la stessa formatted proprietà. Questo è il modo compilatore vede il tuo codice:

extension Float { 
    var formatted: String { 
     get { 
      switch self { 
      case is Float: 
       return "\(self) m" 
      case is Float: 
       return "\(self * 3.6) km/h" 
      default: 
       return "\(self)" 
      } 
     } 
    } 
} 

Credo che è necessario creare piccoli involucri per la funzionalità:

struct Distance { 
    var value: Float 
    var formatted: String { 
     return "\(value) m" 
    } 

    init(_ value: Float) { 
     self.value = value 
    } 
} 

let myDistance = Distance(123) 
myDistance.formatted 
+0

Grazie per la comprensione. Tristemente, in questo modo, non riesco a scrivere: 'let mySpeed: Speed ​​= 30'. Penso che andrò con un'altra soluzione di "formattazione". – gpbl

+0

Con questo approccio è possibile eseguire 'let mySpeed ​​= Speed ​​(30.0)'. – Kirsteins

+0

@crumblenaut guarda questo [articolo] (http://nshipster.com/swift-literal-convertible/) per sapere come implementare l'assegnazione letterale – Antonio