개발/Mobile

[Swift] Swift 강의. 09 - Classes and Structures

hojak99 2018. 3. 13. 13:40

Classes and Structures

이번엔 Class 와 Structure에 대해서 알아보는 시간을 가져보도록 하겠다.

Introduction

Class 와 structure 는 범용적이며, 프로그램 코드의 building block 이 되는 유연한 구조이다. 상수, 변수 및 함수와 동일한 syntax를 사용하여 class 나 structure 에 기능을 추가하는 property, method 를 정의한다.

Swift 에서는 class 나 structure 를 하나의 파일로 정의한다.

Comparing Classes and Structures

스위프트의 class와 structure 에는 많은 공통점이 있다.

  • 값을 저장할 property 정의
  • 기능을 제공할 method 정의
  • 초기 상태를 설정하기 위한 생성자를 정의 등이 있다.

class 에는 structure 에 없는 추가 기능이 있다.

  • 상속을 통해 한 class 는 다른 class 의 특성을 상속 받을 수 있다.
  • type casting 을 사용하면 런타임에 class 인스턴스의 타입을 확인하고 interpret 할 수 있다.
  • Deinitializer 는 class 의 인스턴스에 할당된 모든 리소스를 해제할 수 있게 한다.
  • Reference counting 은 클래스 인스턴스에 대해 둘 이상의 참조를 허용한다.

Examples

아래의 코드는 Class 와 Structure 를 정의하는 코드이다.

class SomeClass {
    // class definition goes here
}

struct SomeStructure {
    // structure definition goes here
}
struct Resolution {
    var width = 0;
    var height = 0;
}

class VideoMode {
    var resolution = Resolution();
    var interlaced = false;
    var frameRate = 0.0;
    var name : String?
}

// structure 나 class 의 인스턴스를 생성할 때는 다음과 같이 작성한다.   
// 참고로 new 연산자나 그런건 사용하지 않는다.
let someResolution = Resolution();
let someVideoMode = VideoMode();

Accessing Properties

property 에 접근할 때는 아래와 같은 코드를 작성한다.

print(someResolution.width);        // 0
print(someVideoMode.resolution.width);      // 0

someVideoMode.resolution.width = 1280;
print(someVideoMode.resolution.width);      // 1280

Properties

property 는 값을 특정 class, structure 또는 enumuration 과 연결해 사용한다. Stored Property는 상수와 변수 값을 인스턴스의 일부로 저장하지만, Computed property 는 값을 저장하지 않고 계산한다.

Stored Properties

// 아래의 property 들은 stored property 이다.
struct FixedLengthRange {
    var firstValue : Int;      
    let length : Int;
}

var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3);

Computed Properties

Computed property 는 값을 저장하는게 아니다. 대신에 getter 와 setter 를 제공해서 다른 property 와 value 를 간접적으로 검색하고 설정한다.
참고로 Swift 에서는 getter 와 setter 는 Java 처럼 직접 get()set() 을 명시해주지 않아도 된다.
다음의 코드를 보면서 이해하자.

struct Point {
    var x = 0.0;
    var y = 0.0;
}

struct Size {
    var width = 0.0;
    var height = 0.0;
}

struct Rect {
    var orgin = Point();
    var size = Size();
    var center = Point {
        get {
            let centerX = origin.x + (size.width / 2);
            let centerY = origin.y + (size.height / 2);
            return Point(x : centerX, y: ceterY);
        }
        set(newCenter) {
            origin.x = newCenter.x - (size.width / 2);
            origin.y = newCenter.y - (size.height / 2);
        }
    }
}

var square = Rect (
    origin: Point(x: 0.0, y: 0.0),
    size: Size(width: 10.0, height: 10.0));

let initialSquareCenter = square.center;
square.center = Point(x: 15.0, y:15.0);

print("square.origin is now at (\(square.origin.x), \(square.origin.y))");
// square.origin is now at (10.0, 10.0)

getter, setter 를 좀 더 짧은 코드로 작성하려면 아래의 코드처럼 작성하면 된다.

struct Cuboid {
    var width = 0.0;
    var height = 0.0;
    var depth = 0.0;
    var volume : Double {
        return width * height * depth;
    }
}

let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0);
print(fourByFiveByTwo.volume);      // 40.0

Property Observers

Property observer 는 속성 값의 변화를 관찰하고 이에 반응한다. Property observer 는 새로운 값이 property 의 현재 값과 같은 경우에도 property 값이 설정될 때마다 호출된다.

  • willSet : willSet 은 값이 저장되기 전에 호출된다.
  • didSet : didSet 은 값이 새로운 값으로 저장된 후 즉시 호출된다.
class StepCounter {
    var totalSteps : Int = 0 {
        willSet (newTotalSteps) {
            print("About to set totalSteps to \(newTotalSteps)");
        }
        didSet {
            if totalSteps > oldValue {
                print("Added \(totalSteps - oldValue) steps");
            }
        }
    }
}

let stepCounter = SteopCounter();
stepCounter.totalSteps = 200;
// About to set totalSteps to 200
// Added 200 steps

stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps

Methods

Method 는 함수다. class 안에 있으면 method, 밖에 있으면 function 이라고 부른다 한다.

Inheritance

class 는 다른 class 의 method, property 및 기타 특성을 상속받을 수 있다.

Subclassing

Subclassing 은 기존 클래스에서 새 클래스를 기초로하는 행위이다. 하위 클래스는 기존 클래스의 특성을 상속하고 수정할 수 있다. 또한, 새 특성을 서브 클래스에 추가할 수도 있다.

class SomeSubclass : SomeSuperClass {
    // subclass definition goes here
}

아래와 같이 상속해서 사용할 수 있다.

class Bicycle {
    var hasBasket = false;
}

class Tandem : Bicycle {
    var currentNumberOfPassengers = 0;
}

let tandem = Tandem();
tandem.hasBasket = true;
tandem.currentNumberOfPassengers = 2;

Overriding

Overriding 은 상위 클래스에서 만든 메소드를 하위 클래스에서 다시 재정의하는 것이다. 이 때 override 라는 키워드를 사용해야 한다.





Classes and Structures

Class

//: Playground - noun: a place where people can play
import UIKit

// 클래스 안에 property 값에 초기화를 안해주면 오류남
class Vehicle {
    var currentSpeed = 0.0;     // stored property
    var description: String {
        return "Traveling at \(currentSpeed) miles per hour";
    }
    
    func makeNoise() {
        print("noiseless");
    }
}

let someVehicle = Vehicle();

someVehicle.currentSpeed = 1.0;
print(someVehicle.currentSpeed);        // "1.0"
someVehicle.makeNoise();                // "noiseless"
print(someVehicle.description);         // "Traveling at 1.0 miles per hour"

// Vehicle 은 부모클래스, Bicycle 은 자식클래스이다.
class Bicycle : Vehicle {
    var hasBasket = false;
}

let someBicycle = Bicycle();
someBicycle.hasBasket = true;
print(someBicycle.hasBasket);       // "true"
someBicycle.currentSpeed = 15.0;
print(someBicycle.description);     // "Traveling at 15.0 miles per hour"

// Bicycle 은 부모클래스, Tandem 은 자식 클래스이다.
class Tandem : Bicycle {
    var currentNumberOfPassengers = 0;
    
    override
    var description: String {
        return "Traveling at \(currentSpeed) miles per hour, number of passenger : \(currentNumberOfPassengers)";
    }
}

let someTandem = Tandem();
someTandem.hasBasket = true;
someTandem.currentNumberOfPassengers = 2;
someTandem.currentSpeed = 22.0;
print("someTandem : \(someTandem.description)");        // "someTandem : Traveling at 22.0 miles per hour, number of passenger : 2"

// Vehicle 은 부모클래스, Train 은 자식클래스이다.
class Train : Vehicle {
    override func makeNoise() {
        print("Choo Choo");
    }
}

let someTrain = Train();
someTrain.makeNoise();      // "Choo Choo"


class Car : Vehicle {
    var gear = 1;
    
    // override 키워드를 붙이는 이유는 상속받는 Vehicle 클래스에도 초기화 메소드인 init() 이 존재하기 때문이다.
    override init(){
        print("Car");
    }
    init(newGear: Int){
        gear = newGear;
    }
}

let someCar = Car();        // "Car"
let someCar2 = Car(newGear: 5);
print(someCar2.gear);       // "5"

Structure

//: Playground - noun: a place where people can play
import UIKit

var name = ["A", "B", "C", "D"];
var age = [3, 4, 5, 6];
var height = [50 , 30, 50, 60];

print(name[0], age[0], height[0]);

// 위의 코드를 struct 를 사용해서 좀 더 편리하게 관리할 수 있다.
// struct 는 class 와 달리 property 에 대한 초기화를 해주지 않아도 된다.
struct Student {
    var name: String;
    var age: Int;
    var height: Int;
}

// 자동으로 초기화를 해주는 메소드를 제공. (생성자라고 생각하면 될 것 같다)
var student1 = Student(name: "A", age: 5, height: 50);
var student2 = Student(name: "B", age: 4, height: 30);
var student3 = Student(name: "C", age: 3, height: 10);

// 아래의 코드가 좀 더 가독성있다.
// print(student1);         // Student(name: "A", age: 5, height: 50)
print(student1.name, student1.age, student1.height);    // "A 5 50"


반응형