欠如

来世は貝になりたい

Swiftの文法について復習してみるObjects and Classes

ツアーもやっと中盤まで行きましたね 今回のテーマはObjects and Classes(オブジェクトとクラス)となります。

Objects and Classes

Use class followed by the class’s name to create a class. 
A property declaration in a class is written the same way as a constant or variable declaration, except that it is in the context of a class. 
Likewise, method and function declarations are written the same way.

クラスを作成するには、クラス名の後にクラスを使用します。
クラス内のプロパティ宣言は、クラスのコンテキスト内にあることを除いて、定数宣言または変数宣言と同じ方法で記述されます。
同様に、メソッドと関数の宣言も同じように記述されます。
class Shape {
    var numberOfSides = 10
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}
print(Shape().simpleDescription())

実行すると以下の通りになります

Linking ./.build/x86_64-unknown-linux/debug/TempCode
A shape with 10 sides.
Create an instance of a class by putting parentheses after the class name. 
Use dot syntax to access the properties and methods of the instance.

クラス名の後に括弧を入れてクラスのインスタンスを作成します。
ドット構文を使用して、インスタンスのプロパティとメソッドにアクセスします。
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

こちらはすでにひとつ前の例に組み込む形になりますが 上のfuncとclassを代入し使いやすくした形になります。 なので結果表示は割愛します。

This version of the Shape class is missing something important: 
an initializer to set up the class when an instance is created. 
Use init to create one.

このバージョンのShapeクラスには、インスタンスの作成時にクラスを設定するためのイニシャライザという重要なものがありません。
initを使用して作成します。
class NamedShape {
    var numberOfSides: Int = 0
    var name: String
    
    init(name: String) {
        self.name = name
    }
    init(){
        self.name = "damy"
    }
    
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}
let test = NamedShape(name:"abs")
print(test.name)
print(NamedShape().simpleDescription())

今回は一部引数を使わない用に引数なしで公式とは変更があります・ ちなみに実行すると以下のような結果が得られます

Linking ./.build/x86_64-unknown-linux/debug/TempCode
abs
A shape with 0 sides.
Notice how self is used to distinguish the name property from the name argument to the initializer. 
The arguments to the initializer are passed like a function call when you create an instance of the class. 
Every property needs a value assigned—either in its declaration (as with numberOfSides) or in the initializer (as with name).

nameプロパティとname引数を初期化子と区別するためにselfがどのように使用されているかに注目してください。
イニシャライザへの引数は、クラスのインスタンスを作成するときに関数呼び出しのように渡されます。
すべてのプロパティは、宣言(numberOfSidesの場合)またはイニシャライザ(nameの場合)のいずれかに値を割り当てる必要があります。
Use deinit to create a deinitializer if you need to perform some cleanup before the object is deallocated.

Subclasses include their superclass name after their class name, separated by a colon. 
There is no requirement for classes to subclass any standard root class, so you can include or omit a superclass as needed.

オブジェクトの割り当てが解除される前にいくつかのクリーンアップを実行する必要がある場合は、deinitを使用してdeinitializerを作成します。

サブクラスは、クラス名の後ろにコロンで区切られたスーパークラス名を含みます。
クラスが標準のルートクラスをサブクラス化する必要はないため、必要に応じてスーパークラスを含めるか省略することができます。
Methods on a subclass that override the superclass’s implementation are marked with override—
overriding a method by accident, without override, is detected by the compiler as an error. 
The compiler also detects methods with override that don’t actually override any method in the superclass.

スーパークラスの実装をオーバーライドするサブクラスのメソッドには、オーバーライドなしでメソッドが
オーバーライドされてマークされ、エラーとしてコンパイラによって検出されます。
また、コンパイラは、スーパークラスのメソッドを実際にオーバーライドしないオーバーライドを持つメソッドも検出します。
class Square: NamedShape {
    var sideLength: Double
    
    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }
    
    func area() -> Double {
        return sideLength * sideLength
    }
    
    override func simpleDescription() -> String {
        return "A square with sides of length \(sideLength)."
    }
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()

前例のNamedShape CLASSを継承し 実行結果は以下となります

Linking ./.build/x86_64-unknown-linux/debug/TempCode
27.04
A square with sides of length 5.2.
In addition to simple properties that are stored, properties can have a getter and a setter.

格納される単純なプロパティに加えて、プロパティにはゲッタとセッタがあります。
class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0
    
    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }
    
    var perimeter: Double {
        get {
            return 3.0 * sideLength
        }
        set {
            sideLength = newValue / 3.0
        }
    }
    
    override func simpleDescription() -> String {
        return "An equilateral triangle with sides of length \(sideLength)."
    }
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.perimeter)
triangle.perimeter = 9.9
print(triangle.sideLength)

前例のNamedShape CLASSを継承し 実行結果は以下となります

Linking ./.build/x86_64-unknown-linux/debug/TempCode
9.3
3.3
In the setter for perimeter, the new value has the implicit name newValue. You can provide an explicit name in parentheses after set.

格納される単純なプロパティに加えて、プロパティにはゲッタとセッタがあります。
Notice that the initializer for the EquilateralTriangle class has three different steps:

1. Setting the value of properties that the subclass declares.
2. Calling the superclass’s initializer.
3. Changing the value of properties defined by the superclass. 
Any additional setup work that uses methods, getters, or setters can also be done at this point.

EquilateralTriangleクラスのイニシャライザには、次の3つのステップがあります。

1.サブクラスが宣言するプロパティの値を設定する。
2.スーパークラスの初期化子を呼び出す。
3.スーパークラスによって定義されたプロパティの値を変更する。
メソッド、ゲッター、またはセッターを使用する追加のセットアップ作業もこの時点で実行できます。
If you don’t need to compute the property but still need to provide code that is run before and after setting a new value, use willSet and didSet. 
The code you provide is run any time the value changes outside of an initializer. 
For example, the class below ensures that the side length of its triangle is always the same as the side length of its square.

プロパティを計算する必要はなく、新しい値を設定する前後に実行されるコードを提供する必要がある場合は、willSetとdidSetを使用します。
指定したコードは、イニシャライザの外部で値が変更されるたびに実行されます。
たとえば、以下のクラスは、三角形の辺の長さが常に四角形の辺の長さと同じであることを保証します。
class TriangleAndSquare {
    var triangle: EquilateralTriangle {
        willSet {
            square.sideLength = newValue.sideLength
        }
    }
    var square: Square {
        willSet {
            triangle.sideLength = newValue.sideLength
        }
    }
    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EquilateralTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
print(triangleAndSquare.square.sideLength)
print(triangleAndSquare.triangle.sideLength)
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
print(triangleAndSquare.triangle.sideLength)
Linking ./.build/x86_64-unknown-linux/debug/TempCode
10.0
10.0
50.0
When working with optional values, you can write ? before operations like methods, properties, and subscripting. 
If the value before the ? is nil, everything after the ? is ignored and the value of the whole expression is nil.
 Otherwise, the optional value is unwrapped, and everything after the ? acts on the unwrapped value. 
In both cases, the value of the whole expression is an optional value.

オプションの値を使って作業するときは? メソッド、プロパティ、およびサブスクリプトのような操作の前に。
?の前の値が? 無名:すべての後に? は無視され、式全体の値はnilになります。
  それ以外の場合、オプションの値はラップされず、? ラップされていない値に作用します。
どちらの場合も、式全体の値はオプションの値です。
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength

以下が実行結果となります

Optional(2.5)

長くなりましたが続きは次回書きます。