protocolは{get set}であるか、{get}であるかを要請するだけです。
それが定数でも変数でも要請に従ていれば全く問題がありません。
準拠する側が任意に以下のようにできます。
swift
1struct Car: Vehicle {
2 var fuel: Float
3 var fuelEfficeint: Float = 10
4
5 mutating func drive(mile: Float) {
6 fuel -= mile * fuelEfficeint
7 }
8
9 func showFuel() {
10 print("fuel is", fuel)
11 }
12}
ここで、fuelEfficientが定数ではなく変数となっていますが、protocol Vehicle の要請する{get}「fuelEfficientの値を取得すること」が出来ますので、これで全く問題ありません。
あるいは
swift
1class Car {
2
3 private let full: Float = 1000
4 private var useFuel: Float = 0
5
6 var fuel: Float {
7 get {
8 return full - useFuel
9 }
10 set(newValue) {
11 useFuel -= newValue - fuel
12 useFuel = min(useFuel, full)
13 }
14 }
15 var fuelEfficeint: Float = 10
16
17
18 func drive(mile: Float) {
19 useFuel += mile * fuelEfficeint
20 }
21
22 func showFuel() {
23 print("fuel is", fuel)
24 }
25}
のようにcomputed propertyとすることもできます。
protocolの要請はあくまでも、取得と設定ができるか、あるいは取得ができるかだけであり、その要請に従っていれば、変数であっても定数であってもcomputed propertyであっても関係ありません。
この考えを理解するにはprotocolを「使う側」と「使われる側」に分けて考える必要があります。
以下に使う側から見たprotocolを例示します。
少し難しいかもしれませんが、これが一番わかりやすいと思います。
前提条件として、protocol Vehicleに準拠した型はCarだけではなくそのほかのもの多数存在しているとします。
swift
1// この関数は様々な機械のインスタンスを返します。Vehicle だけどは限りません。
2let anyMachine: Any = getMachine()
3
4// このif文はanyMachineがVehicleに準拠していれば真となり、定数 vehicle にそのインスタンスをVehicleとして代入します。
5// ただし、実際の型が何であるかはわかりません。また、その必要がありません。
6if let vehicle = anyMachine as? Vehicle {
7
8 // vehicleがprotocol Vehicleに準拠していることが確定しているので、showFuel()メソッドが使用可能です。
9 vehicle.showFuel()
10
11 // protocol VehicleはfuelEfficeintへのsetを許していませんので、下のステートメントはエラーとなります。
12 // vehicle.fuelEfficeint = 200
13
14}
このように使う側は実際の型が何であるかはわからないが、protocol Vehicleに準拠したインスタンスであることを調べることでprotocol Vehicleのプロパティやメソッドを使用できるようになります。
この場合、使う側は struct Car の存在を知らなくても全く問題がありません。