한국어 | English | 日本語
Webアプリケーションエンジニア (経験8.8年)
技術・開発
engineering
ウェブフロントエンドと バックエンド開発を扱います

Swift 4+ の文法における `open` キーワードについて理解する

継承はオブジェクト指向の華ですが、誤って使用すると、基底クラスの変更がサブクラスを破壊する「脆弱な基底クラス」問題を引き起こします。現代の言語であるSwiftが、この問題を文法的にどのように強制して解決しているのかを探ります。
継承に伴う副作用を防ぐため、デフォルトですべてのクラスを継承不可(final)に設定しているSwiftとKotlinのアクセス制御方式を分析します。特に、クラスおよびメソッドレベルで継承許可範囲を精密に制御する`open`キーワードの使用法をJavaと比較して説明します。

アクセス修飾子 (Access Modifier)

プログラミング言語、例えばJavaを例にとると、public, private, protected は、フィールド、関数、クラスへのアクセス範囲を制御するために使用されます。final, open, override, abstract のような継承関連のキーワードも「アクセス修飾子」の範疇に含まれます。(アクセス修飾子は可視性修飾子 (Visibility Modifier) と呼ばれることもあります)

脆弱な基底クラス (Fragile Base Class)

脆弱な基底クラス問題は、継承によって発生する問題で、基底クラスとそれを継承するサブクラスがある場合、基底クラスの変更が発生するとサブクラスが壊れる問題を意味します。基底クラスをサブクラスが継承する際に、どのメソッドをどのようにオーバーライドするかについての規則が明示されていないと、サブクラスは意図と異なる方法で任意のメソッドをオーバーライドすることができます。また、基底クラスのメソッドの目的が変更された場合、サブクラスのオーバーライドメソッドは既存の意図と予期せぬ形で異なってしまうため、基底クラスの変更はそれを継承するすべてのサブクラスに影響を与えます。これを基底クラスが脆弱であるという意味で、脆弱な基底クラスと呼びます。

初期のオブジェクト指向プログラミング言語に該当するJava、C#、C++の場合、オブジェクト指向の特徴である継承が容易になるように、アクセス修飾子を特に明示しない限り、すべての基本クラスは継承が可能です。しかし、脆弱な基底クラス問題を防止するため、『Effective Java』の著者も「継承のための設計と文書を用意するか、それができないなら継承を禁止せよ」と述べているように、すべての基本クラスは継承しないことをソフトウェアアーキテクチャおよびデザインパターンで推奨しています。

初期のオブジェクト指向プログラミングを使用する中で発見された限界や問題は、言語を継続的にアップデートすることで補完されることもありますが、新しい言語はこれらの良いパターンを自分たちの特徴として取り入れることもあります。現代のオブジェクト指向プログラミング言語であるKotlinとSwiftがその一つです。冗談めかしてこのような言語を「チャンポン」(様々な要素が混ざり合っている、ごちゃ混ぜ)と呼ぶこともありますが、それだけパターンを文法として強制する利点を持っています。

Swift, Kotlin では Java と異なりデフォルトで継承不可

Java は脆弱な基底クラス問題を持つ初期のプログラミング言語として、デフォルトですべての基本クラスは継承が可能です。Kotlin と Swift は、この問題解決のためにデフォルトですべての基本クラスを継承不可(final)にしています。したがって、Swift の2つのタイプである class と struct はどちらもデフォルトで継承不可です。

さらに、Java の変数、クラス、関数はすべて、デフォルトで何もアクセス修飾子を明示しなければ package-private で宣言されますが、Kotlin と Swift の場合、何もアクセス修飾子を明示しなければ public で宣言され、どこからでも使用できます。そして public はデフォルトで final であり、継承は不可能です。

open class User {
    open func login() { }
    public func playGame() { }
    public init() { }
}

Kotlin、Swift ともに、継承を行うためにはクラス、関数、変数すべてに open キーワードを追加する必要があります。関数と変数に open キーワードを使用することで、クラス全体レベルではなく、関数、変数レベルで「継承可能なもの」と「継承不可能なもの」を容易に管理できるという利点があります。


これまで見てきたように、JavaとKotlin、Swiftの継承に対する扱いは完全に逆です。public なクラスや関数をデフォルトで継承可能にし、継承を制限するために privateprotected のようなアクセス修飾子を使用するJavaとは異なり、Kotlin、Swift は開発者に対してデフォルトで全て継承不可能にした上で、そこから追加で継承を行うためには open を明示するように制限することで、誤った継承を防ぎます。そのため、Swift で open を使用していると、関数、変数単位での継承の可否を決定するため、Java の abstract と似たような感覚を受けることがあります。


Swift 4+ の文法における `open` キーワードについて理解する
Author
Aaron
Posted on
Licensed Under
CC BY-NC-SA 4.0
CC BY-NC-SA 4.0
同じカテゴリーの関連記事
最新記事
LLMフィルターが奪う会話の筋肉とコミュニケーション様式
会話における無礼さを濾過し、洗練された回答を生成するLLMツールが日常化した現代において、私たちは本当に思慮深い会話をしているのだろうか?リアルタイムのコミュニケーションにおける数多くの失敗を通じて磨かれるべき会話能力が、外部ツールに依存することで退化している現象と、それがもたらす社会的な不安や世代間の行動様式の変化について考察する。
シニア採用における年俸交渉の最適なタイミングと戦略
年俸交渉は単なる数字の交換ではなく、心理的な駆け引きとタイミングが重要です。本稿では、企業側にとって、候補者が計算的な態度を取りがちな最終合格後よりも、採用プロセスの初期段階から段階的に交渉を進めることが、なぜより効率的であり、率直な情報の共有に繋がるのかを考察します。
法治主義の限界と人間の多様性
全ての人間の行為を単一の法体系で規制できるという信念は、傲慢であるかもしれない。この記事は、中世の階層的な統制から脱却し、現代の無限の自由を手に入れた人類が直面する法治主義の逆説と、多様性という名のもとに深化する社会的強制力と他者への悪魔化現象を鋭く分析する。
토스트 예시 메세지