見出し画像

楽しい!Swift。 - A Swift Tour (Objects and Classes)

Classを使って処理の方法をひとまとまりすることができます。基本な形は、

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

class 名前 {
  プロパティ
  メソッド
}

という形になっています。Class内でプロパティ(定数や変数)を宣言、同様に、メソッド(関数)の宣言します。

実行する場合はClassは処理の方法をひとまとめにしてあるだけなのでこれを実際に使える形にしないといけません(実際に使えるようにすることを"インスタンスを生成する"と言います)。

var shape = Shape()

変数にClassを代入することでインスタンスを生成することができます。実際に動かしてみましょう。

shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()

print(shapeDescription)

A shape with 7 sides.

と出力されます。

classでは初期化が必要な場合があります。

class NamedShape {
    var numberOfSides: Int = 0
    var name: String

    init(name: String) {
       self.name = name
    }

    func simpleDescription() -> String {
       return "A shape with \(numberOfSides) sides."
    }
}

var name: String

変数nameを型のみで宣言した時は初期化が必須です。

init(name: String) {
  self.name = name
}

init()で初期化、イニシャライズします。

新しclassを作り時に別のクラスを参照させることができます。先ほど作った NamedShapeを参照してサブクラスSquareを作ります。NamedShapeをスーパークラスと呼びます。

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()

スーパークラスて定義されているように初期化する場合は"super"

super.init(name: name)

とします。

同じメソッドを使う時は"override"

override func simpleDescription() -> String { return "A square with sides of length \(sideLength)." }

を使います。

プロパティの他にget と set を持つこともできます。いわゆる"computedプロパティ"

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)
// Prints "9.3"

triangle.perimeter = 9.9

print(triangle.sideLength)
// Prints "3.3000000000000003"

perimeter の setterを使いデータをセットします。新しい値は暗黙的に newValue という名前になります。set の後に丸括弧(())で囲んで明示的に指定することもできます。getは受けた値について計算します。この場合は

3 * sideLength  ・・・ 3倍します

EquilateralTriangle クラスで使われている初期化ですが3パターンあります。

  1. サブクラス(今宣言しているクラス)で宣言されたプロパティに値を設定します

  2. スーパークラス(参照しているクラス)のイニシャライザ(init)を呼びます

  3. スーパークラスで定義されたプロパティの値を変更。この時点で get や set やメソッドを使用して他のセットアップ処理を実行できます

プロパティを計算する必要はないけれども、新しい値を設定する前後で何かコードを実行したい場合、willSetdidSet を使います。このコードは、イニシャライザ以外で値が変更された時に毎回実行されます。例えば、下のクラスは三角形の辺の長さが常に四角形の辺の長さと同じになります。

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)
// Prints "10.0"

print(triangleAndSquare.triangle.sideLength)
// Prints "10.0"

triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
print(triangleAndSquare.triangle.sideLength)
// Prints "50.0"

オプショナル値を扱う場合、? をメソッド、プロパティ、サブスクリプトのような操作の前に書きます。もし ? の前の値が nil の場合、? の後の処理は全て無視され、その式全体の値は nil になります。それ以外、オプショナル値はアンラップされて、? の後は全てアンラップされた値として実行されます。どちらの場合も、式全体はオプショナル値です

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength


この記事が気に入ったらサポートをしてみませんか?