Article

Choosing Between Structures and Classes 構造体かクラスのいずれかを選ぶ

Decide how to store data and model behavior. どのようにデータを格納して挙動をモデル化するか決定を下します。

Overview 概要

Structures and classes are good choices for storing data and modeling behavior in your apps, but their similarities can make it difficult to choose one over the other. 構造体とクラスは、あなたのアプリにおけるデータ格納と挙動モデル化のための良い選択です、しかしそれらの類似点は他方より一方を選ぶのを難しくするかもしれません。

Consider the following recommendations to help choose which option makes sense when adding a new data type to your app. 以下の忠告を考慮して、どちらの選択が道理にかなっているか、新しいデータ型をあなたのアプリに追加する時に選択する助けにしてください。

  • Use structures by default. 構造体を、通常は使ってください。

  • Use classes when you need Objective-C interoperability. クラスを、あなたがObjective-C互換性を必要とする場合に使ってください。

  • Use classes when you need to control the identity of the data you're modeling. クラスを、あなたがモデル化しているデータの同一性を制御する必要がある場合に使ってください。

  • Use structures along with protocols to adopt behavior by sharing implementations. 構造体をそれだけでなくプロトコルと一緒に使うことで、実装を共有することによる挙動を取り入れてください。

Choose Structures by Default 構造体を通常は使ってください

Use structures to represent common kinds of data. Structures in Swift include many features that are limited to classes in other languages: They can include stored properties, computed properties, and methods. Moreover, Swift structures can adopt protocols to gain behavior through default implementations. The Swift standard library and Foundation use structures for types you use frequently, such as numbers, strings, arrays, and dictionaries. 構造体を使って、通常の種類のデータを表してください。Swiftでのさまざまな構造体は、他の言語ではクラスに限られる多くの機能を含みます:それらは格納プロパティ、計算プロパティ、そしてメソッドを含むことができます。その上さらに、Swift構造体はプロトコルを採用することで、省略時の実装を通して挙動を獲得できます。Swift標準ライブラリとFoundationは、あなたが頻繁に使う型、例えば数、文字列、配列、そして辞書などに対して構造体を使います。

Using structures makes it easier to reason about a portion of your code without needing to consider the whole state of your app. Because structures are value types—unlike classes—local changes to a structure aren't visible to the rest of your app unless you intentionally communicate those changes as part of the flow of your app. As a result, you can look at a section of code and be more confident that changes to instances in that section will be made explicitly, rather than being made invisibly from a tangentially related function call. 構造体を使うことは、あなたのアプリの全体の状態を考える必要なしに、あなたのコードの一部について結論を下すことを簡単にします。構造体が値型であることから — クラスとは違い — 構造体への局所的変更はあなたのアプリの残りには不可視です、あなたが意図的にそれら変更をあなたのアプリのフローの一部として伝達しない限りは。結果として、あなたはコードのある区画を調べて、その区画のインスタンスに対する変更が明確だということを、ほとんど無関係な関連する関数呼び出しから不可視に行われるよりむしろずっと自信を持てます。

Use Classes When You Need Objective-C Interoperability クラスをあなたがObjective-C互換性を必要とする場合に使ってください

If you use an Objective-C API that needs to process your data, or you need to fit your data model into an existing class hierarchy defined in an Objective-C framework, you might need to use classes and class inheritance to model your data. For example, many Objective-C frameworks expose classes that you are expected to subclass. あなたのデータを処理するのに必要であるObjective-C APIをあなたが使う、またはあなたのデータモデルをObjective-Cフレームワークにおいて定義される既存のクラス階層へと適合させる必要があるならば、あなたはクラスとクラス階層を使ってあなたのデータをモデル化する必要があるかもしれません。例えば、多くのObjective-Cフレームワークは、あなたがサブクラスを作るべき様々なクラスを公開します。

Use Classes When You Need to Control Identity あなたが同一性を制御する必要がある場合はクラスを使ってください

Classes in Swift come with a built-in notion of identity because they're reference types. This means that when two different class instances have the same value for each of their stored properties, they're still considered to be different by the identity operator (===). It also means that when you share a class instance across your app, changes you make to that instance are visible to every part of your code that holds a reference to that instance. Use classes when you need your instances to have this kind of identity. Common use cases are file handles, network connections, and shared hardware intermediaries like CBCentralManager. Swiftでのクラスそれらは、組み込みの同一性の概念を備えています、なぜならそれらが参照型だからです。これは、2つの異なるクラスインスタンスが同じ値をそれらの格納プロパティの各々に対して持つ場合に、それらはまだ異なっていると同一性演算子(===)によってみなされることを意味します。それはまた、あなたがあるクラスインスタンスをあなたのアプリの至る所で共有する場合、あなたがそのインスタンスになす変更は、そのインスタンスに対する参照を保持するあなたのコードのあらゆる部分で見ることができます。あなたのインスタンスがその種の同一性を持つことをあなたが必要とする場合は、クラスを使ってください。一般的な利用事例は、ファイルハンドル、ネットワーク接続、そしてCBCentralManagerのような共有ハードウェア仲介です。

For example, if you have a type that represents a local database connection, the code that manages access to that database needs full control over the state of the database as viewed from your app. It's appropriate to use a class in this case, but be sure to limit which parts of your app get access to the shared database object. 例えば、あなたがローカルデータベース接続を表す型を持つならば、そのデータベースへのアクセスを管理するコードは、データベースの状態すべてわたって完全な制御をあなたのアプリから眺められる際に必要とします。この場合にはクラスを使うのが適切です、しかしあなたのアプリのどの部分が共有データベースオブジェクトに対するアクセスを手に入れるかに限界を設けることを確実にしてください。

Use Structures When You Don't Control Identity あなたが同一性を制御しない場合は構造体を使ってください

Use structures when you're modeling data that contains information about an entity with an identity that you don't control. あなたが制御を行わない同一性をもつある存在についての情報を含むデータをあなたがモデル化する場合は、構造体を使ってください。

In an app that consults a remote database, for example, an instance's identity may be fully owned by an external entity and communicated by an identifier. If the consistency of an app's models is stored on a server, you can model records as structures with identifiers. In the example below, jsonResponse contains an encoded PenPalRecord instance from a server: 例えば、リモートデータベースに助言を求めるアプリでは、あるインスタンスの持つ同一性は、外部存在によって完全に所有され、そしてある識別子によって伝えられるかもしれません。あるアプリの持つモデルの一貫性がサーバ上に格納されるならば、あなたはレコードを、識別子を使って構造体としてモデル化できます。下の例において、jsonResponseは、あるサーバからのエンコード済みPenPalRecordインスタンスを含みます。


struct PenPalRecord {
    let myID: Int
    var myNickname: String
    var recommendedPenPalID: Int
}


var myRecord = try JSONDecoder().decode(PenPalRecord.self, from: jsonResponse)

Local changes to model types like PenPalRecord are useful. For example, an app might recommend multiple different penpals in response to user feedback. Because the PenPalRecord structure doesn't control the identity of the underlying database records, there's no risk that the changes made to local PenPalRecord instances accidentally change values in the database. PenPalRecordのようなモデル型に対するローカルな変更は、役に立ちます。例えば、あるアプリはユーザのフィードバックに答えて複数の異なる文通友達を勧めるかもしれません。PenPalRecord構造体が基礎をなすデータベースレコードの同一性を制御しないことから、ローカルのPenPalRecordインスタンスになされる変更が誤って値をデータベースにおいて変更する危険はありません。

If another part of the app changes myNickname and submits a change request back to the server, the most recently rejected penpal recommendation won't be mistakenly picked up by the change. Because the myID property is declared as a constant, it can't change locally. As a result, requests to the database won't accidentally change the wrong record. アプリの別の部分がmyNicknameを変更するそして変更要請をサーバに提出するとしても、最近拒否した文通友達推薦が、その変更によって間違って拾い上げられることはないでしょう。なぜならmyIDプロパティは定数として宣言されるからです、それはローカルに変更できません。結果として、データベースに対する要請は誤って相応しくないレコードを変更することはありません。

Use Structures and Protocols to Model Inheritance and Share Behavior 構造体とプロトコルを使って挙動の継承と共有をモデル化してください

Structures and classes both support a form of inheritance. Structures and protocols can only adopt protocols; they can't inherit from classes. However, the kinds of inheritance hierarchies you can build with class inheritance can be also modeled using protocol inheritance and structures. 構造体とクラスは両方とも継承の形式をサポートします。構造体とプロトコルは、プロトコルの採用だけが可能です;それらはクラスから継承できません。しかしながら、あなたがクラス継承で構築できる種類の継承階層はまた、プロトコル継承と構造体を使ってモデル化できます。

If you're building an inheritance relationship from scratch, prefer protocol inheritance. Protocols permit classes, structures, and enumerations to participate in inheritance, while class inheritance is only compatible with other classes. When you're choosing how to model your data, try building the hierarchy of data types using protocol inheritance first, then adopt those protocols in your structures. あなたが継承関係をゼロから構築するならば、プロトコル継承を選んでください。プロトコルは、クラス、構造体、そして列挙に対して継承に参加することを許可します、一方でクラス継承は他のクラスと互換性があるだけです。あなたのデータをモデル化する方法をあなたが選ぶ時、データ型の階層の構築を最初にプロトコル継承を使って試みてください、それからそれらのプロトコルをあなたの構造体において採用してください。

See Also 参照

Data Modeling データモデリング