クラス

構造体との違い
クラスの基本
構造体とクラス

構造体との違い

まず同じところ。
値やメソッドを持てる。
持っている値にアクセスする関数っぽいやつがある
初期化するための関数を作れる
拡張とかプロトコルとか使える?
英語難しい。

クラスのとくちょう。
継承して特徴を引き継げる。
実行時型をチェックしたり解釈したりできる?
参照カウントで複数参照ができる??
英語は、難しい。

クラスの基本

クラスのつくりかた。

class SomeClass {
	//いろいろ。
}

あとはクラス・フィールド・メソッド名のキャメルケースにご用心。例えばこんな感じ。

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

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

コンストラクタはinit{ ~ }で。自分のクラスのフィールド・メソッドを指すのはself.~。

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

	init(name: String) {
		self.name = name
	}
	func simpleDescription() -> String {
		return "A shape with \(numberOfSides) sides."
	}
}

ちなみにデストラクタはdeinit。
サブクラスを作るときは「class クラス名: スーパークラス」、みたいな感じで。関数がオーバーライドされる場合はoverrideと書く。
親を指すときは「super.~」。

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

フィールドに対するゲッターとセッターは、getとsetと書けばできちゃう。なんかいじりたいときに。
なお、getとsetを使うなら両方書かないとダメみたい。

class EquilateralTriangle: NamedShape {
	var sideLength: Double = 0.0

	init(sideLength: Double, name: String) {
		//サブクラス(自分)の持っているフィールドをセット
		self.sideLength = sideLength
		//スーパークラス(NamedShape)のコンストラクタを呼ぶ
		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")
//ゲッターがはたらく
triangle.perimeter
//セッターがはたらく
triangle.perimeter = 9.9
triangle.sideLength

どこかの値を変えたときに、別の値も連動して変わってほしいということがあるかもしれない(あるの?)。
次の例では、三角形と四角形のsidelengthが常に同じ値になるようになっている。

class TriangleAndSquare {
	var triangle: EquilateralTriangle {
	willSet {
		//var triangleの値が変更されるとsquare.sideLengthの値も書き変わる
		square.sideLength = newValue.sideLength
	}
	}

	var square: Square {
	willSet {
		//var squareの値が変更されるとtriangle.sideLengthの値も書き変わる
		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")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength

triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
triangleAndSquare.triangle.sideLength

トリガーとなるフィールドに対してwillSetを設定してやればよい。なお、didSetというのもあり、どっちも値の変更を検知して働くのだが、willSetはトリガーになる値の変更の前に、didSetはトリガーとなる値の変更の後に実行されるという違いがあるっぽい。
実行順としては「willSet内の命令→値の変更→didSet内の命令」か。

クラス内のメソッドの使い方はこんな感じ。

class Counter {
	var count: Int = 0
	func incrementBy(amount: Int, numberOfTimes times: Int) {
		count += amount * times
	}
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)

こちらはオプショナルな値。この例ではSquareかnilの入る定数(Square?型定数)になっている。
仮にoptionalSquareの中身がnilで、その後optionalSquareのsideLengthを使うことになってしまってもnilが代入されるだけで終わる。optionalSquareのうしろの「?」はつけないとエラー。

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

構造体とクラス

を、両方使ってみる例。

struct Resolution {
	//Int型のプロパティ
	var width = 0
	var height = 0
}
class VideoMode {
	var resolution = Resolution()	//ピクセル解像度
	var interlaced = false	//falseであるということはいわゆるノンインタレース
	var frameRate = 0.0
	var name: String?
}

まあインスタンスの作成方法はどっちも同じ。

let someResolution = Resolution()
let videoMode = VideoMode()

値を見たり書き換えたりしたいときはドットで。someVideoModeの中のresolutionの中のwidthもドットでつなげていくことで直接扱える。

//The width of someResolution is 0
println("The width of someResolution is \(someResolution.width)")
//The width of someVideoMode is 0
println("The width of someVideoMode is \(someVideoMode.resolution.width)")

someVideoMode.resolution.width = 1280
//The width of someVideoMode is now 1280
println("The width of someVideoMode is now \(someVideoMode.resolution.width)")

↑ PAGE TOP