2014-10-24 17 views
6

tôi đang đối phó với các đơn vị khác nhau, tức là distance, altitude, speed, volume vvMở rộng bí danh gõ nhanh chóng

Mục tiêu của tôi là phải có một phong cách độc đáo tao nhã để định dạng chúng trong ứng dụng, ví dụ như gọi số myValue.formatted:

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

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

Tôi nghĩ đây là trường hợp tốt để sử dụng bí danh loại.

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

Đối với formatted bất động sản, tôi đã cố gắng với một extension loại 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)" 
      } 
     } 
    } 
} 

Nhưng trình biên dịch nói rằng case khối của tôi là luôn true.

Sau đó, tôi đã cố gắng để mở rộng các loại hình duy nhất:

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

trình biên dịch hiện nay nêu rõ khai báo lại không hợp lệ của 'định dạng'

OK, thì rõ ràng hiện nay như thế nào loại bí danh hoạt động. Nhưng làm thế nào tôi có thể nhận được tài sản .formatted của mình cho các loại khác nhau của Floats nhanh chóng?

Trả lời

5

typealias chỉ cần thay đổi hoặc đổi tên các loại. Nó không tạo ra một loại người dùng khác cho bạn. Bạn đang thực sự mở rộng Float cho Speed, Altitude một lần nữa.

Bạn có thể vượt qua 180 vào cấu trúc tùy chỉnh của mình bằng cách tuân thủ các loại Literals.

let mySpeed: Speed = 180 

FloatLiteralConvertibleIntegerLiteralConvertible sẽ cung cấp cho bạn nhiều chức năng giống bạn muốn và bạn có thể trực tiếp gán giá trị cho khách hàng của bạn struct types như bạn gán cho 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

Điều này thực sự rất thú vị. Đó là một chút thất vọng tôi không thể cast một 'floatVar như Speed', tức là sử dụng từ khóa' as'. Bí danh kiểu được thanh lịch theo cách này. – gpbl

+0

@crumblenaut bạn nói đúng. Tốc độ hiện không phải là 'Float'. Đây là loại tùy chỉnh do người dùng xác định.Bạn có thể 'định dạng'' Float' với một hàm bằng một loại.Nếu bạn thực sự muốn làm điều đó, hãy sử dụng 'định dạngSpeed', định dạngDistance trong phần mở rộng. – codester

1

Distance, AltitudeSpeed luôn cùng loại - Float và chia sẻ cùng một thuộc tính formatted. Đây là cách biên dịch thấy mã của bạn:

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)" 
      } 
     } 
    } 
} 

Tôi đoán bạn cần phải tạo ra giấy gói nhỏ cho các chức năng của bạn:

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

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

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

Cảm ơn bạn đã hiểu biết. Thật đáng buồn khi làm theo cách này tôi không thể viết: 'để cho mySpeed: Speed ​​= 30'. Tôi nghĩ tôi sẽ đi với một giải pháp "định dạng" khác. – gpbl

+0

Bạn có thể thực hiện 'cho phép tốc độ của tôi = Tốc độ (30.0)' với phương pháp này. – Kirsteins

+0

@crumblenaut nhìn vào [bài viết] này (http://nshipster.com/swift-literal-convertible/) để biết cách thực hiện bài tập theo nghĩa đen – Antonio

Các vấn đề liên quan