構造体とクラス
日本語を消す 英語を消す下記URLから引用し、日本語訳をつけてみました。
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures
Model custom types that encapsulate data.
データをカプセル化するカスタム タイプをモデル化します。
Structures and classes are general-purpose, flexible constructs that become the building blocks of your program’s code. You define properties and methods to add functionality to your structures and classes using the same syntax you use to define constants, variables, and functions.
構造体とクラスは、プログラムのコードの構成要素となる汎用の柔軟な構造です。 定数、変数、関数の定義に使用するのと同じ構文を使用して、プロパティとメソッドを定義し、構造体とクラスに機能を追加します。
Unlike other programming languages, Swift doesn’t require you to create separate interface and implementation files for custom structures and classes. In Swift, you define a structure or class in a single file, and the external interface to that class or structure is automatically made available for other code to use.
他のプログラミング言語とは異なり、Swift では、カスタム構造およびクラス用に個別のインターフェイス ファイルと実装ファイルを作成する必要がありません。 Swift では、単一のファイルで構造体またはクラスを定義すると、そのクラスまたは構造体への外部インターフェイスが他のコードで使用できるように自動的に作成されます。
Note
注釈
An instance of a class is traditionally known as an object. However, Swift structures and classes are much closer in functionality than in other languages, and much of this chapter describes functionality that applies to instances of either a class or a structure type. Because of this, the more general term instance is used.
クラスのインスタンスは伝統的にオブジェクトとして知られています。 ただし、Swift の構造とクラスは、他の言語よりもはるかに機能的に近く、この章の多くは、クラスまたは構造型のインスタンスに適用される機能について説明しています。 このため、より一般的な用語「インスタンス」が使用されます。
Comparing Structures and Classes
構造体とクラスの比較
Structures and classes in Swift have many things in common. Both can:
Swift の構造とクラスには多くの共通点があります。 どちらも次のことができます。
- Define properties to store values
- 値を保存するプロパティを定義する
- Define methods to provide functionality
- 機能を提供するメソッドを定義する
- Define subscripts to provide access to their values using subscript syntax
- 添字構文を使用して値にアクセスできるように添字を定義します。
- Define initializers to set up their initial state
- イニシャライザを定義して初期状態を設定する
- Be extended to expand their functionality beyond a default implementation
- デフォルトの実装を超えて機能を拡張するために拡張される
- Conform to protocols to provide standard functionality of a certain kind
- プロトコルに準拠して、特定の種類の標準機能を提供します
For more information, see Properties, Methods, Subscripts, Initialization, Extensions, and Protocols.
詳細については、「プロパティ」、「メソッド」、「サブスクリプト」、「初期化」、「拡張機能」、「プロトコル」を参照してください。
Classes have additional capabilities that structures don’t have:
クラスには、構造体にはない追加の機能があります。
- Inheritance enables one class to inherit the characteristics of another.
- 継承により、あるクラスが別のクラスの特性を継承できるようになります。
- Type casting enables you to check and interpret the type of a class instance at runtime.
- 型キャストを使用すると、実行時にクラス インスタンスの型を確認して解釈できます。
- Deinitializers enable an instance of a class to free up any resources it has assigned.
- 初期化解除子を使用すると、クラスのインスタンスが割り当てられたリソースを解放できます。
- Reference counting allows more than one reference to a class instance.
- 参照カウントにより、クラス インスタンスへの複数の参照が許可されます。
For more information, see Inheritance, Type Casting, Deinitialization, and Automatic Reference Counting.
詳細については、「継承」、「型キャスト」、「初期化解除」、「自動参照カウント」を参照してください。
The additional capabilities that classes support come at the cost of increased complexity. As a general guideline, prefer structures because they’re easier to reason about, and use classes when they’re appropriate or necessary. In practice, this means most of the custom types you define will be structures and enumerations. For a more detailed comparison, see Choosing Between Structures and Classes(Link:developer.apple.com).
クラスがサポートする追加機能には、複雑さの増加が伴います。 一般的なガイドラインとして、推論しやすい構造体を優先し、適切または必要な場合にはクラスを使用します。 実際には、これは、定義するカスタム型のほとんどが構造体と列挙型になることを意味します。 より詳細な比較については、「構造体とクラスの選択(Link:developer.apple.com)(英語)」を参照してください。
Note
注釈
Classes and actors share many of the same characteristics and behaviors. For information about actors, see Concurrency.
クラスとアクターは、多くの同じ特性と動作を共有します。 アクターについて詳しくは、「同時実行性」をご覧ください。
Definition Syntax
定義構文
Structures and classes have a similar definition syntax. You introduce structures with the struct
keyword and classes with the class
keyword. Both place their entire definition within a pair of braces:
構造体とクラスの定義構文は似ています。 struct
キーワードを使用して構造を導入し、class
キーワードを使用してクラスを導入します。 どちらも定義全体を一対の中括弧内に置きます。
struct SomeStructure {
// structure definition goes here
}
class SomeClass {
// class definition goes here
}
Note
注釈
Whenever you define a new structure or class, you define a new Swift type. Give types UpperCamelCase
names (such as SomeStructure
and SomeClass
here) to match the capitalization of standard Swift types (such as String
, Int
, and Bool
). Give properties and methods lowerCamelCase
names (such as frameRate
and incrementCount
) to differentiate them from type names.
新しい構造またはクラスを定義するたびに、新しい Swift 型を定義します。 標準の Swift 型(String
、Int
、Bool
など)の大文字と小文字の区別に合わせて、型に UpperCamelCase
の名前(ここでは SomeStructure
や SomeClass
など)を付けます。 プロパティとメソッドには、型名と区別するために、lowerCamelCase
の名前 (frameRate
や incrementCount
など) を付けます。
Here’s an example of a structure definition and a class definition:
構造体定義とクラス定義の例を次に示します。
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
The example above defines a new structure called Resolution
, to describe a pixel-based display resolution. This structure has two stored properties called width
and height
. Stored properties are constants or variables that are bundled up and stored as part of the structure or class. These two properties are inferred to be of type Int
by setting them to an initial integer value of 0
.
上の例では、ピクセルベースのディスプレイ解像度を記述するために、Resolution
という新しい構造を定義しています。 この構造には、width
とheight
さと呼ばれる 2 つの保存されたプロパティがあります。 保存されたプロパティは、構造体またはクラスの一部としてバンドルされて保存される定数または変数です。 これら 2 つのプロパティは、初期整数値 0
に設定することで、Int
型であると推測されます。
The example above also defines a new class called VideoMode
, to describe a specific video mode for video display. This class has four variable stored properties. The first, resolution
, is initialized with a new Resolution
structure instance, which infers a property type of Resolution
. For the other three properties, new VideoMode
instances will be initialized with an interlaced
setting of false
(meaning “noninterlaced video”), a playback frame rate of 0.0
, and an optional String
value called name
. The name
property is automatically given a default value of nil
, or “no name
value”, because it’s of an optional type.
上記の例では、ビデオ表示用の特定のビデオ モードを記述するために、VideoMode
という新しいクラスも定義しています。 このクラスには 4 つの変数格納プロパティがあります。 1 つ目のresolution
は、新しいResolution
構造インスタンスで初期化され、Resolution
のプロパティ タイプが推測されます。 他の 3 つのプロパティについては、新しい VideoMode
インスタンスは、interlaced
設定 false
(「非インターレース ビデオ」を意味します)、再生フレーム レート 0.0
、およびオプションの name
というString
値で初期化されます。 name
プロパティには、オプショナルタイプであるため、デフォルト値の nil
または「no name
value」が自動的に与えられます。
Structure and Class Instances
構造体とクラスのインスタンス
The Resolution
structure definition and the VideoMode
class definition only describe what a Resolution
or VideoMode
will look like. They themselves don’t describe a specific resolution or video mode. To do that, you need to create an instance of the structure or class.
Resolution
構造体定義と VideoMode
クラス定義は、Resolution
または VideoMode
がどのようになるかを記述するだけです。 それら自体は、特定の解像度やビデオ モードについては説明しません。 これを行うには、構造体またはクラスのインスタンスを作成する必要があります。
The syntax for creating instances is very similar for both structures and classes:
インスタンスを作成するための構文は、構造体とクラスの両方で非常に似ています。
let someResolution = Resolution()
let someVideoMode = VideoMode()
Structures and classes both use initializer syntax for new instances. The simplest form of initializer syntax uses the type name of the class or structure followed by empty parentheses, such as Resolution()
or VideoMode()
. This creates a new instance of the class or structure, with any properties initialized to their default values. Class and structure initialization is described in more detail in Initialization.
構造体とクラスは両方とも、新しいインスタンスに対して初期化子構文を使用します。 初期化子構文の最も単純な形式では、Resolution()
や VideoMode()
など、クラスまたは構造体の型名の後に空の括弧が続きます。 これにより、クラスまたは構造体の新しいインスタンスが作成され、プロパティはデフォルト値に初期化されます。 クラスと構造体の初期化については、「初期化」で詳しく説明します。
Accessing Properties
プロパティへのアクセス
You can access the properties of an instance using dot syntax. In dot syntax, you write the property name immediately after the instance name, separated by a period (.
), without any spaces:
ドット構文を使用してインスタンスのプロパティにアクセスできます。 ドット構文では、インスタンス名の直後にプロパティ名をスペースを入れずにピリオド (.) で区切って記述します。
print("The width of someResolution is \(someResolution.width)")
// Prints "The width of someResolution is 0"
In this example, someResolution.width
refers to the width
property of someResolution
, and returns its default initial value of 0
.
この例では、someResolution.width
は someResolution
の width
プロパティを参照し、デフォルトの初期値 0
を返します。
You can drill down into subproperties, such as the width
property in the resolution
property of a VideoMode
:
VideoMode
のresolution
プロパティのwidth
プロパティなどのサブプロパティまで掘り下げられます。
print("The width of someVideoMode is \(someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is 0"
You can also use dot syntax to assign a new value to a variable property:
ドット構文を使用して、変数プロパティに新しい値を割り当てることもできます。
someVideoMode.resolution.width = 1280
print("The width of someVideoMode is now \(someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is now 1280"
Memberwise Initializers for Structure Types
構造体型のメンバーごとの初期化子
All structures have an automatically generated memberwise initializer, which you can use to initialize the member properties of new structure instances. Initial values for the properties of the new instance can be passed to the memberwise initializer by name:
すべての構造体には、自動的に生成されたメンバーごとの初期化子があり、これを使用して新しい構造体インスタンスのメンバー プロパティを初期化できます。 新しいインスタンスのプロパティの初期値は、名前によってメンバーごとの初期化子に渡すことができます。
let vga = Resolution(width: 640, height: 480)
Unlike structures, class instances don’t receive a default memberwise initializer. Initializers are described in more detail in Initialization.
構造体とは異なり、クラス インスタンスはデフォルトのメンバーごとの初期化子を受け取りません。 イニシャライザについては、「初期化」で詳しく説明します。
Structures and Enumerations Are Value Types
構造体と列挙型は値の型です
A value type is a type whose value is copied when it’s assigned to a variable or constant, or when it’s passed to a function.
値型とは、値が変数や定数に割り当てられるとき、または関数に渡されるときにコピーされる型です。
You’ve actually been using value types extensively throughout the previous chapters. In fact, all of the basic types in Swift — integers, floating-point numbers, Booleans, strings, arrays and dictionaries — are value types, and are implemented as structures behind the scenes.
実際、これまでの章では値の型を広範囲に使用してきました。 実際、Swift のすべての基本型 (整数、浮動小数点数、ブール値、文字列、配列、辞書) は値型であり、バックグラウンドで構造体として実装されます。
All structures and enumerations are value types in Swift. This means that any structure and enumeration instances you create — and any value types they have as properties — are always copied when they’re passed around in your code.
Swift では、すべての構造体と列挙型は値型です。 これは、作成した構造体と列挙型のインスタンス、およびそれらがプロパティとして持つ値の型は、コード内で渡されるときに常にコピーされることを意味します。
Note
注釈
Collections defined by the Swift standard library like arrays, dictionaries, and strings use an optimization to reduce the performance cost of copying. Instead of making a copy immediately, these collections share the memory where the elements are stored between the original instance and any copies. If one of the copies of the collection is modified, the elements are copied just before the modification. The behavior you see in your code is always as if a copy took place immediately.
配列、辞書、文字列などの Swift 標準ライブラリによって定義されたコレクションは、コピーのパフォーマンス コストを削減するために最適化を使用します。 これらのコレクションは、すぐにコピーを作成するのではなく、元のインスタンスとコピーの間で要素が保存されているメモリを共有します。 コレクションのコピーの 1 つが変更された場合、要素は変更の直前にコピーされます。 コード内で見られる動作は、常にコピーが即座に行われたかのようになります。
Consider this example, which uses the Resolution
structure from the previous example:
前の例のResolution
構造を使用する次の例を考えてみましょう。
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
This example declares a constant called hd
and sets it to a Resolution
instance initialized with the width and height of full HD video (1920 pixels wide by 1080 pixels high).
この例では、hd
という定数を宣言し、フル HD ビデオの幅と高さ(幅 1920 ピクセル、高さ 1080 ピクセル)で初期化された解像度インスタンスに設定します。
It then declares a variable called cinema
and sets it to the current value of hd
. Because Resolution
is a structure, a copy of the existing instance is made, and this new copy is assigned to cinema
. Even though hd
and cinema
now have the same width and height, they’re two completely different instances behind the scenes.
次に、cinema
という変数を宣言し、それを hd
の現在の値に設定します。 Resolution
は構造体であるため、既存のインスタンスのコピーが作成され、この新しいコピーがシネマに割り当てられます。 HD とシネマの幅と高さは同じですが、舞台裏では 2 つのまったく異なるインスタンスです。
Next, the width
property of cinema
is amended to be the width of the slightly wider 2K standard used for digital cinema projection (2048 pixels wide and 1080 pixels high):
次に、cinema
のwidth
プロパティが、デジタル シネマ投影に使用されるわずかに広い 2K 標準の幅(幅 2048 ピクセル、高さ 1080 ピクセル)になるように修正されます。
cinema.width = 2048
Checking the width
property of cinema
shows that it has indeed changed to be 2048
:
cinema
の width
プロパティを確認すると、実際に 2048
に変更されていることがわかります。
print("cinema is now \(cinema.width) pixels wide")
// Prints "cinema is now 2048 pixels wide"
However, the width
property of the original hd
instance still has the old value of 1920
:
ただし、元の hd
インスタンスのwidth
プロパティには、1920
という古い値が残ります。
print("hd is still \(hd.width) pixels wide")
// Prints "hd is still 1920 pixels wide"
When cinema
was given the current value of hd
, the values stored in hd
were copied into the new cinema
instance. The end result was two completely separate instances that contained the same numeric values. However, because they’re separate instances, setting the width of cinema
to 2048
doesn’t affect the width stored in hd
, as shown in the figure below:
cinema
に hd
の現在の値が与えられると、hd
に保存されている値が新しいcinema
インスタンスにコピーされました。 最終的には、同じ数値を含む 2 つの完全に別個のインスタンスが生成されました。 ただし、これらは別個のインスタンスであるため、下の図に示すように、cinema
の幅を 2048
に設定しても、hd
に保存される幅には影響しません。
The same behavior applies to enumerations:
同じ動作が列挙型にも適用されます。
enum CompassPoint {
case north, south, east, west
mutating func turnNorth() {
self = .north
}
}
var currentDirection = CompassPoint.west
let rememberedDirection = currentDirection
currentDirection.turnNorth()
print("The current direction is \(currentDirection)")
print("The remembered direction is \(rememberedDirection)")
// Prints "The current direction is north"
// Prints "The remembered direction is west"
When rememberedDirection
is assigned the value of currentDirection
, it’s actually set to a copy of that value. Changing the value of currentDirection
thereafter doesn’t affect the copy of the original value that was stored in rememberedDirection
.
rememberedDirection
に currentDirection
の値が割り当てられると、実際にはその値のコピーに設定されます。 その後 currentDirection
の値を変更しても、rememberedDirection
に保存されている元の値のコピーには影響しません。
Classes Are Reference Types
クラスは参照型です
Unlike value types, reference types are not copied when they’re assigned to a variable or constant, or when they’re passed to a function. Rather than a copy, a reference to the same existing instance is used.
値の型とは異なり、参照型は変数や定数に割り当てられるとき、または関数に渡されるときにコピーされません。 コピーではなく、同じ既存のインスタンスへの参照が使用されます。
Here’s an example, using the VideoMode
class defined above:
上記で定義した VideoMode
クラスを使用した例を次に示します。
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
This example declares a new constant called tenEighty
and sets it to refer to a new instance of the VideoMode
class. The video mode is assigned a copy of the HD resolution of 1920
by 1080
from before. It’s set to be interlaced, its name is set to "1080i"
, and its frame rate is set to 25.0
frames per second.
この例では、tenEighty
という新しい定数を宣言し、VideoMode
クラスの新しいインスタンスを参照するように設定します。 ビデオ モードには、1920
x 1080
の HD 解像度のコピーが割り当てられます。 インターレース(走査線を一本おきに伝送する仕組み)に設定され、名前は「1080i
」に設定され、フレームレートは 25.0
フレーム/秒に設定されています。
Next, tenEighty
is assigned to a new constant, called alsoTenEighty
, and the frame rate of alsoTenEighty
is modified:
次に、tenEighty
が alsoTenEighty
という新しい定数に割り当てられ、altoTenEighty
のフレーム レートが変更されます。
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
Because classes are reference types, tenEighty
and alsoTenEighty
actually both refer to the same VideoMode
instance. Effectively, they’re just two different names for the same single instance, as shown in the figure below:
クラスは参照型であるため、tenEighty
と alsoTenEighty
は実際には両方とも同じ VideoMode
インスタンスを参照します。 実際には、以下の図に示すように、これらは同じ 1 つのインスタンスに対する 2 つの異なる名前にすぎません。
Checking the frameRate
property of tenEighty
shows that it correctly reports the new frame rate of 30.0
from the underlying VideoMode
instance:
tenEighty
の frameRate
プロパティを確認すると、基になる VideoMode
インスタンスから新しいフレーム レート 30.0
が正しく報告されていることがわかります。
print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// Prints "The frameRate property of tenEighty is now 30.0"
This example also shows how reference types can be harder to reason about. If tenEighty
and alsoTenEighty
were far apart in your program’s code, it could be difficult to find all the ways that the video mode is changed. Wherever you use tenEighty
, you also have to think about the code that uses alsoTenEighty
, and vice versa. In contrast, value types are easier to reason about because all of the code that interacts with the same value is close together in your source files.
この例は、参照型の推論がいかに難しいかを示しています。 プログラムのコード内で tenEighty
と alsoTenEighty
が大きく離れている場合、ビデオ モードが変更されるすべての方法を見つけるのが困難になる可能性があります。 tenEighty
を使用する場合は常に、tenEighty
を使用するコードについても考慮する必要があり、その逆も同様です。 対照的に、値の型は、同じ値を操作するすべてのコードがソース ファイル内で近くにあるため、推論が容易です。
Note that tenEighty
and alsoTenEighty
are declared as constants, rather than variables. However, you can still change tenEighty.frameRate
and alsoTenEighty.frameRate
because the values of the tenEighty
and alsoTenEighty
constants themselves don’t actually change. tenEighty
and alsoTenEighty
themselves don’t “store” the VideoMode
instance — instead, they both refer to a VideoMode
instance behind the scenes. It’s the frameRate
property of the underlying VideoMode
that’s changed, not the values of the constant references to that VideoMode
.
tenEighty
と alsoTenEighty
は変数ではなく定数として宣言されていることに注意してください。 ただし、tenEighty
および alsoTenEighty
の定数自体の値は実際には変更されないため、tenEighty.frameRate
および alsoTenEighty.frameRate
を変更することはできます。 tenEighty
と tenEighty
自体は、VideoMode
インスタンスを「保存」しません。代わりに、どちらも舞台裏で VideoMode
インスタンスを参照します。 変更されるのは、基になる VideoMode
の frameRate
プロパティであり、その VideoMode
への定数参照の値ではありません。
Identity Operators
アイデンティティ演算子
Because classes are reference types, it’s possible for multiple constants and variables to refer to the same single instance of a class behind the scenes. (The same isn’t true for structures and enumerations, because they’re always copied when they’re assigned to a constant or variable, or passed to a function.)
クラスは参照型であるため、複数の定数と変数がバックグラウンドでクラスの同じ単一インスタンスを参照することが可能です。 (構造体と列挙型については同様ではありません。構造体や列挙型は定数や変数に代入されるとき、または関数に渡されるときに常にコピーされるからです。)
It can sometimes be useful to find out whether two constants or variables refer to exactly the same instance of a class. To enable this, Swift provides two identity operators:
2 つの定数または変数がクラスのまったく同じインスタンスを参照しているかどうかを確認すると便利な場合があります。 これを可能にするために、Swift は 2 つの アイデンティティ 演算子を提供します。
- Identical to (
===
) - 同一(
===
) - Not identical to (
!==
) - 同一ではない(
!==
)
Use these operators to check whether two constants or variables refer to the same single instance:
これらの演算子を使用して、2 つの定数または変数が同じ単一インスタンスを参照しているかどうかを確認します。
if tenEighty === alsoTenEighty {
print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}
// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."
Note that identical to (represented by three equal signs, or ===
) doesn’t mean the same thing as equal to (represented by two equal signs, or ==
). Identical to means that two constants or variables of class type refer to exactly the same class instance. Equal to means that two instances are considered equal or equivalent in value, for some appropriate meaning of equal, as defined by the type’s designer.
「同一」(3 つの等号で表される、または ===
)は、「等しい」(2 つの等号、または ==
で表される)と同じ意味ではないことに注意してください。 「同一」とは、クラス型の 2 つの定数または変数がまったく同じクラス インスタンスを参照していることを意味します。 「等しい」とは、タイプの設計者によって定義された、等しいという適切な意味で、2 つのインスタンスの値が等しいか同等であるとみなされることを意味します。
When you define your own custom structures and classes, it’s your responsibility to decide what qualifies as two instances being equal. The process of defining your own implementations of the ==
and !=
operators is described in Equivalence Operators.
独自のカスタム構造とクラスを定義する場合、2 つのインスタンスが等しいとみなされる条件を決定するのはユーザーの責任です。 ==
演算子と !=
演算子の独自の実装を定義するプロセスについては、等価演算子で説明されています。
Pointers
ポインタ
If you have experience with C, C++, or Objective-C, you may know that these languages use pointers to refer to addresses in memory. A Swift constant or variable that refers to an instance of some reference type is similar to a pointer in C, but isn’t a direct pointer to an address in memory, and doesn’t require you to write an asterisk (*
) to indicate that you are creating a reference. Instead, these references are defined like any other constant or variable in Swift. The Swift standard library provides pointer and buffer types that you can use if you need to interact with pointers directly — see Manual Memory Management(Link:developer.apple.com).
C、C++、または Objective-C の使用経験がある場合は、これらの言語がポインタを使用してメモリ内のアドレスを参照していることをご存じかもしれません。 何らかの参照型のインスタンスを参照する Swift の定数または変数は C のポインターに似ていますが、メモリ内のアドレスへの直接ポインターではなく、それを示すためにアスタリスク (*
) を書く必要はありません。 参照を作成していることを示します。 代わりに、これらの参照は、Swift の他の定数や変数と同様に定義されます。 Swift 標準ライブラリには、ポインタを直接操作する必要がある場合に使用できるポインタとバッファのタイプが用意されています。「手動メモリ管理(Link:developer.apple.com)(英語)」を参照してください。