質問: Swiftのプロパティの型表現で題記のような表現を行うにはどのようなコードを書く必要があるでしょうか? Swiftのバージョンは3.0です。 具体的な例としては下記のような状況でプロトコルViewResizableのviewプロパティがUIViewのインスタンスもしくはサブクラスのインスタンスである場合に、ViewShowableで宣言されているメソッドを実装していることを保証したいです。 ViewResizableを採用するクラスがプロパティとして持つviewはViewShowableを採用しているクラスです。ViewResizableのviewプロパティでその特定のクラスを指定することもできますが、ViewShowableを採用するクラスは様々なクラスが考えられるためそれでは、特定のクラス毎にプロトコルを宣言しなくてはなりません。 そのため、プロパティの記述(ジェネリクス等何かしらの方法)で特定の型のインスタンスでかつプロトコルを採用しているインスタンスを表現することでコードの記述量を減らしたいです。 ``` protocol ViewShowable { func show() func hide() } protocol ViewResizable { // 下の行はエラーになるが、viewからViewShowableのメソッドを呼び出したい var view: UIView & ViewShowable! { get } } extension ViewResizable { func resizeAndShow() { ビューのフレーム変更コード // showメソッドを呼び出したい view.show() } } ``` アドバイスいただけると助かります。 よろしくお願いします。
回答: プロトコルとプロトコル拡張に型による制約をつけること、さらに利用するクラスでのジェネリクスの活用により可能なことが分かりました。 コードは次の通りです。 ``` protocol ViewShowable { func show() func hide() } protocol ViewResizable { associatedtype View var view: View! { get } } extension ViewResizable where View: UIView, View: ViewShowable { func resizeAndShow() { // 次のコードはエラーにならない print("\(self.view.bounds.size)") // 次のコードも呼び出せる self.view.show() } } // UIViewとViewShowableに適合するクラス class ShowableView: UIView, ViewShowable { func show() { print("show") } func hide() { print("hide") } } // ジェネリクスクラスでの宣言 class Test: ViewResizable where T: ViewShowable { var view: T! func test() { // 次のコードを呼び出せる self.resizeAndShow() } } // ジェネリクスクラスの呼び出し時にはジェネリクスの型による制約に適合している具体的なクラスを指定 let test = Test() ``` 上記のコードはプレイグランドでエラーなく実行できました。 ただし、ジェネリクスクラスではstatic格納型プロパティに対応していないエラー及び@objcが付いているメソッドに対応していないエラーが出たため、UIViewControllerでの採用を検討していた私のコードではこの2つのハードルを越えるのは難しく、利用を断念しました。