月 火 水 木 土 金 日 格闘技A 格闘技B格闘技C スタジ …M10/02/25 千葉ジェッツ チアリーディング リトルクラス (3歳~小1) 16:00~16:50
はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech
-
Upload
tomohiro-kumagai -
Category
Software
-
view
1.169 -
download
5
Transcript of はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech
![Page 1: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/1.jpg)
![Page 2: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/2.jpg)
![Page 4: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/4.jpg)
![Page 5: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/5.jpg)
![Page 6: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/6.jpg)
![Page 7: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/7.jpg)
![Page 8: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/8.jpg)
![Page 9: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/9.jpg)
class HogeOperation { private(set) var isPrepared = false func prepare() { guard !isPrepared else { fatalError("prepare を複数回呼ばないこと") }
isPrepared = true } }
![Page 10: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/10.jpg)
// Init 状態の HogeOperation を生成 let operation = HogeOperation<Init>()
// 最初は prepared を呼べて準備完了したものを取得可能 let preparedOp = operation.prepared()
// 準備が終われば prepared はビルドエラーで実行不可 preparedOp.prepared()
![Page 11: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/11.jpg)
![Page 12: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/12.jpg)
// これで "操作状態を表現する型" を表現 protocol OperationState {}
// 操作状態ごとにクラスを定義 class Init: OperationState {} class Prepared: OperationState {}
![Page 13: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/13.jpg)
// 型パラメーターで型に状態を付与 class HogeOperation<State: OperationState> {
/* 今回は内部で、 型パラメーターを使わないのがポイント */
}
![Page 14: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/14.jpg)
extension HogeOperation where State: Init {
// 準備を実行し、準備完了状態のインスタンスを返す func prepared() -> HogeOperation<Prepared> {…} }
extension HogeOperation where State: Prepared {
// 目的の操作を実行する func execute() {…} }
![Page 15: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/15.jpg)
![Page 16: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/16.jpg)
let operation = HogeOperation<Init>()
// Init 状態では、まだ execute は存在しない operation.execute()
// prepared を呼ぶことで Prepared 状態のものを取得 let preparedOp = operation.prepared()
// Prepared 状態には、もう prepared は存在しない preparedOp.prepared()
![Page 17: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/17.jpg)
![Page 18: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/18.jpg)
![Page 19: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/19.jpg)
![Page 20: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/20.jpg)
![Page 21: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/21.jpg)
![Page 22: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/22.jpg)
let operation = HogeOperation<Init>()
// HogeOperation<Init> 型だから prepared が呼べる let preparedOp: HogeOperation<Prepared>() = operation.prepared()
// HogeOperation<Prepared> 型だから execute が呼べる preparedOp.execute()
// Init クラスや Prepared クラスを、実行時には使わない // ビルドの段階で、もう役目が済んでいる
![Page 23: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/23.jpg)
![Page 24: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/24.jpg)
let operation = HogeOperation<Init>() let preparedOp = operation.prepared()
let type1 = type(of: operation)
let type2 = type(of: preparedOp)
type1 == type2 // false
![Page 25: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/25.jpg)
// 型パラメーターで型に状態を付与 class HogeOperation<State: OperationState> {
/* 内部では、型パラメーターを使っていない 型の在り方を説明するためだけに使っている */
![Page 26: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/26.jpg)
![Page 27: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/27.jpg)
/// Phantom Type に出逢う前の認識
// Array はテンプレート的なもので… struct Array<Element> { }
// 型パラメーターによって、異なる型になる let values: Array<Int> = Array<String>()
![Page 28: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/28.jpg)
![Page 29: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/29.jpg)
// protocol OperationState {}
// class Init: OperationState {} // class Prepared: OperationState {}
![Page 30: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/30.jpg)
class Operation { fileprivate var data: OperationData fileprivate init(data: OperationData) { self.data = data } func mob() {} }
![Page 31: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/31.jpg)
class OperationInit: Operation {
convenience init() {…} func prepared() -> OperationPrepared {…} }
class OperationPrepared: Operation {
func execute() {…} }
![Page 32: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/32.jpg)
let operation = OperationInit() let preparedOp = operation.prepared()
preparedOp.execute()
![Page 33: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/33.jpg)
![Page 34: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/34.jpg)
struct OperationInit {
fileprivate var data: OperationData fileprivate init(data: OperationData) {…}
// 共通機能 func mob() {}
// 固有の機能 init() {…} func prepared() -> OperationPrepared {…} }
![Page 35: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/35.jpg)
struct OperationPrepared {
fileprivate var data: OperationData fileprivate init(data: OperationData) {…}
// 共通機能 func mob() {}
// 固有の機能 func execute() {…} }
![Page 36: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/36.jpg)
let operation = OperationInit() let preparedOp = operation.prepared()
preparedOp.execute()
![Page 37: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/37.jpg)
protocol Operation {}
struct OperationInit: Operation {
… }
struct OperationPrepared: Operation {
… }
![Page 38: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/38.jpg)
![Page 39: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/39.jpg)
struct Operation {
struct Init {
… }
struct Prepared {
… } }
![Page 40: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/40.jpg)
let operation = Operation.Init() let preparedOp = operation.prepared()
preparedOp.execute()
![Page 41: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/41.jpg)
![Page 42: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/42.jpg)
class Operation { fileprivate var data: OperationData fileprivate init(data: OperationData) { self.data = data } func mob() {} }
![Page 43: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/43.jpg)
extension Operation {
class Init: Operation {
… }
class Prepared: Operation {
… } }
![Page 44: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/44.jpg)
let operation = Operation.Init() let preparedOp = operation.prepared()
preparedOp.execute()
![Page 45: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/45.jpg)
![Page 46: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/46.jpg)
![Page 47: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/47.jpg)
![Page 48: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/48.jpg)
![Page 49: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/49.jpg)
class HogeOperation<State: OperationState> { func mob() {…} }
extension HogeOperation where State: Init { func prepared() -> HogeOperation<Prepared> {…} }
extension HogeOperation where State: Prepared { func execute() {…} }
![Page 50: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/50.jpg)
let operation = HogeOperation<Init>()
operation.execute()
![Page 51: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/51.jpg)
let operation = OperationInit()
operation.execute()
![Page 52: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/52.jpg)
![Page 53: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/53.jpg)
// 準備前と準備後を、自分自身や同じ変数に書き戻せない var operation = HogeOperation<Init>() operation = operation.prepared()
![Page 54: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/54.jpg)
protocol Operation {} class HogeOperation<State: OperationState>: Operation { }
var op: Operation
op = HogeOperation<Init>()
op = (op as! HogeOperation<Init>).prepared() op = (op as! HogeOperation<Prepared>).execute()
![Page 55: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/55.jpg)
![Page 56: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/56.jpg)
class Driver {
init(channel: Int? = nil, volume: Int? = nil, pan: Int? = nil, format: Format? = nil, route: Route? = nil) { } }
// 設定項目に何があるかや、設定順番に気を使う let driver = Driver(volume: 10, format: ulaw, route: .speaker)
![Page 57: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/57.jpg)
// 本体のクラスを Phantom Type で定義して… class Driver<State> where State: AudioState {
}
// 準備が整ったときの機能を実装し… extension Driver where State: Ready {
func start() { … } }
![Page 58: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/58.jpg)
// 初期化中にできることを規定すると… extension Driver where State: Setup {
func prepared() -> Driver<Ready> { … }
func set(channel: Int) -> Driver { return self } func set(volume: Int) -> Driver { return self } func set(pan: Int) -> Driver { return self } func set(format: Format) -> Driver { return self } func set(route: Route) -> Driver { return self } }
![Page 59: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/59.jpg)
// 初期設定では、順番を気にせず設定できる・補完が効く let driver = Driver<Setup>() .set(format: ulaw) .set(volume: 10) .set(route: .speaker) .prepared() // ここで Driver<Ready>() を返す
// 設定完了を宣言 (prepared) して、使い始める driver.start()
![Page 60: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/60.jpg)
let driver = Driver<Setup>()
.format //→ Driver<FormatSetup> .set(sampleRate: 44100) .set(channelsPerFrame: 2)
.general //→ Driver<GeneralSetup> .set(volume: 10) .set(route: .speaker)
.prepared() //→ Driver<Ready>
![Page 61: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/61.jpg)
let driver = Driver.setup() //→ DriverSetup
.format //→ FormatSetup .set(sampleRate: 44100) .set(channelsPerFrame: 2)
.general //→ AudioSetup .set(volume: 10) .set(route: .speaker)
.prepared() //→ Driver
![Page 62: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/62.jpg)
![Page 63: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/63.jpg)
// 設定項目を、初期値を持った構造体で用意して… struct Description {
var channel: Int = default var volume: Int = default var pan: Int = default var format: Format = default var route: Route = default }
![Page 64: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/64.jpg)
let description = Description()
description.format.sampleRate = 44100 description.format.channelsPerFrame = 2 description.volume = 10 description.route = .speaker
![Page 65: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/65.jpg)
// Driver は Description で初期化するようにして… class Driver {
init(description: Description) { … }
}
// 設定項目を渡して、初期化を完成する let driver = Driver(description: description)
![Page 66: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/66.jpg)
![Page 67: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/67.jpg)
![Page 68: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/68.jpg)
class Controller { var environment: Environment<Neutral> }
![Page 69: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/69.jpg)
struct Environment<State> {
fileprivate(set) var platform: Platform fileprivate(set) var version: Double
func startEditing() -> Environment<Editing> {
return Environment<Editing>( platform: platform, version: version) } }
![Page 70: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/70.jpg)
extension Environment where State: Editing {
mutating func set(platform: Platform) { … } mutating func set(version: Double) { … }
func endEditing() -> Environment<Neutral> {
return Environment<Neutral>( platform: platform, version: version) } }
![Page 71: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/71.jpg)
func update() {
// 編集状態で取り出さないと、書き込めない var environment = self.environment.startEditing()
environment.set(platform: .macOS) environment.set(version: Platform.macOS.latest) // ローカルで編集を終了したら、書き戻す self.environment = environment.endEditing() }
![Page 72: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/72.jpg)
![Page 73: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/73.jpg)
extension Environment where State: Editing {
var platform: Platform var version: Double
// 同じ内容の、別インスタンスを作り直している func endEditing() -> Environment<Neutral> {
return Environment<Neutral>( platform: platform, version: version) }
![Page 74: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/74.jpg)
extension Environment where State: Editing {
// 内容を原始的にコピーしないといけないとき func endEditing() -> Environment<Neutral> {
var result = Environment<Neutral>()
result.platform = platform result.version = version
return result }
![Page 75: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/75.jpg)
![Page 76: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/76.jpg)
struct Environment<State> { fileprivate(set) var platform: Platform fileprivate(set) var version: Double } extension Environment { fileprivate init<S>(takeover: Environment<S>) { platform = takeover.platform version = takeover.version } }
![Page 77: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/77.jpg)
extension Environment where State: Editing {
func endEditing() -> Environment<Neutral> {
return Environment<Neutral>(takeover: self) }
}
![Page 78: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/78.jpg)
![Page 79: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/79.jpg)
struct Environment<State> {
// データをここで集中管理する fileprivate struct Context {
var platform: Platform var version: Double }
// これだけを引き継げば済む状況を作る fileprivate var _context: Context }
![Page 80: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/80.jpg)
extension Environment {
fileprivate init(context: Context) {
_context = context } }
![Page 81: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/81.jpg)
extension Environment where State: Editing {
func endEditing() -> Environment<Neutral> {
return Environment<Neutral>(context: _context) }
}
![Page 82: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/82.jpg)
extension Environment {
var platform: Platform {
get { _context.platform } set { _context.platform = newValue } } var version: Double {
get { _context.version } set { _context.version = newValue } }
![Page 83: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/83.jpg)
![Page 84: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/84.jpg)
extension Environment where State: Editing {
func endEditing() -> Environment<Neutral> {
// 準備不要で、いきなりビットキャスト可能 return unsafeBitCast(self, to: Environment<Neutral>.self) }
}
![Page 85: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/85.jpg)
extension Environment {
fileprivate init<S>(takeover: Environment<S>) {
self = unsafeBitCast(takeover, to: Environment.self) } }
![Page 86: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/86.jpg)
let sub: Base = Sub() let base: Base = Base()
// 実体が Sub なので、全ての機能が使える let obj: Sub = unsafeBitCast(sub, to: Sub.self)
// 実体が Base なので、Sub の機能を使うとクラッシュする let obj: Sub = unsafeBitCast(base, to: Sub.self)
![Page 87: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/87.jpg)
![Page 88: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/88.jpg)
![Page 89: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/89.jpg)
class Test: OperationState {}
extension HogeOperation where State: Test {
func testSomething() {…} }
extension HogeOperation where State: Init {
func testing() -> HogeOperation<Test> {…} }
![Page 90: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/90.jpg)
![Page 91: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/91.jpg)
// Test 状態を Prepared から継承させれば… class Test: Prepared {}
// Test には Prepared の機能も備わる extension HogeOperation where State: Prepared { func execute() {…} } extension HogeOperation where State: Test { func testSomething() {…} }
![Page 92: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/92.jpg)
![Page 93: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/93.jpg)
![Page 94: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/94.jpg)
![Page 95: はじめて Phantom と遭遇して、闇雲に闘いを挑んでみた話 #kbkz_tech](https://reader031.fdocument.pub/reader031/viewer/2022012318/587123991a28abe4448b59f3/html5/thumbnails/95.jpg)