[swift] 13. Inheritance (상속)


상속이란 부모가 자식에게 재산을 몰려주는 행위
상속을 사용할 땐 다음과 같이 한다.

class 클래스 이름: 부모 클래스 이름 {
    // 하위 클래스 정의
}




클래스 상속


상속

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {

    }
}

class Bicycle: Vehicle {
    var hasBasket = false
}

var bicycle = Bicycle()
bicycle.currentSpeed = 15.0
print("bicycle.currentSpeed: \(bicycle.currentSpeed)")

출력 결과

bicycle.currentSpeed: 15.0



Override

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        print("speaker on")
    }
}

class Train: Vehicle {
    override func makeNoise() {
        super.makeNoise()
        print("choo choo")
    }
}

let train = Train()
print("train.makeNoise: \(train.makeNoise)")

출력 결과

train.makeNoise: speaker on
choo choo



프로퍼티 상속

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        print("speaker on")
    }
}

class Car: Vehicle {
    var gear = 1
    override var description: String {
        return super.description + " in gear \(gear)"
    }
}

let car = Car()
car.currentSpeed = 30.0
car.gear = 2
print("car.description: \(car.description)")

출력 결과

car.description: traveling at 30.0 miles per hour in gear 2



상속된 프로퍼티 override를 사용해서 프로퍼티 옵저버를 추가

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        print("speaker on")
    }
}

class AutomaticCar: Car {
    override var currentSpeed: Double {
        didSet{
            gear = Int(currentSpeed / 10) + 1
        }
    }
}

let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")

출력 함수

AutomaticCar: traveling at 35.0 miles per hour in gear 4



final

class Vehicle {
    final var currentSpeed = 0.0 // final이므로 재정의할 수 없다.
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        print("speaker on")
    }
}

class AutomaticCar: Car {
    override var currentSpeed: Double { // ERROR (final로 인한 재정의 불가)
        didSet{
            gear = Int(currentSpeed / 10) + 1   // ERROR (final로 인한 재정의 불가)
        }
    }
}

[swift] 12. 클래스와 구조체의 차이


클래스와 구조체의 공통점

  • 값을 저장할 프로퍼티를 선언할 수 있다.
  • 함수적 기능을 하는 메서드를 선언 할 수 있다.
  • 내부 값에 . 을 사용하여 접근할 수 있다.
  • 생성자를 사용해 초기 상태를 설정할 수 있다.
  • extension을 사용하여 기능을 확장할 수 있다.
  • Protocol을 채택하여 기능을 설정할 수 있다.



클래스와 구조체의 차이점


클래스

  • 참조 타입
  • ARC로 메모리를 관리한다.
  • 상속이 가능하다.
  • 타입 캐스팅을 통해 런타임에서 클래스 인스턴스의 타입을 확인할 수 있다.
  • deinit을 사용하여 클래스 인스턴스의 메모리 할당을 해제할 수 있다.
  • 같은 클래스 인스턴스를 여러 개의 변수에 할당한 뒤 값을 변경시키면 모든 변수에 영향을 준다.(메모리가 복사 된다.)

구조체

  • 값 타입
  • 구조체 변수를 새로운 변수에 할당할 때마다 새로운 구조체가 할당된다.
  • 같은 구조체를 여러 개의 변수에 할당한 뒤 값을 변경시키더라도 다른 변수에 영향을 주지 않는다.(값 자체를 복사)




예제


클래스

class SomeClass {
    var count: Int = 0
}

var class1 = SomeClass()
var class2 = class1
var class3 = class1

class3.count = 2
print("class1.count: \(class1.count)")

출력 결과

class1.count: 2


구조체

struct SomeStruct {
    var count: Int = 0
}

var struct1 = SomeStruct()
var struct2 = struct1
var struct3 = struct1

struct2. count = 3
struct3. count = 4

print("struct1.count: \(struct1.count)")
print("struct2.count: \(struct2.count)")
print("struct3.count: \(struct3.count)")

출력 결과

struct1.count: 0
struct2.count: 3
struct3.count: 4

[swift] 11. Property (프로퍼티)


프로퍼티란 클래스, 구조체 또는 열거형 등에 관련된 값을 뜻한다.

프로퍼티는 저장 프로퍼티, 연산 프로퍼티, 타입 프로퍼티가 존재한다.
저장 프로퍼티는 인스턴스의 변수 또는 상수를 의미한다.
연산 프로퍼티는 값을 저장하는 것이 아닌, 특정 연산을 실행하는 결과 값을 저장한다.
타입 프로퍼티는 특정 타입에서 사용하는 프로퍼티이다.




저장 프로퍼티

// 저장 프로퍼티
struct Dog {
    var name: String
    let gender: String
}

var dog = Dog(name: "이준혁", gender: "Male")
print(dog)

dog.name = "김철수"
// dog.gender = "Female" -> Error (let이므로)

let dog2 = Dog(name: "김철수", gender: "Male")
// dog2.name = "김철수" -> Error (구조체 인스턴스가 상수이기 때문에.)

//클래스는 상수로 선언해도 인스턴스에서 변경이 가능하지만, 구조체는 상수로 선언할 경우 인스턴스에서 변경이 불가하다.

class Cat {
    var name: String
    let gender: String

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

let cat = Cat(name: "json", gender: "Male")
cat.name = "gunter"
print("cat.name: \(cat.name)")

출력 결과

Dog(name: "이준혁", gender: "Male")
cat.name: gunter




연산 프로퍼티

struct Stock {
    var averagePrice: Int
    var quantity: Int
    var purchasePrice: Int {    // 게터 세터를 사용한 연산형 프로퍼티
        get {
            return averagePrice * quantity
        }
        set(newPrice) {
            averagePrice = newPrice / quantity
        }
    }
}

var stock = Stock(averagePrice: 2300, quantity: 3)
print("stock: \(stock)")
print("stock.purchasePrice: \(stock.purchasePrice)")
stock.purchasePrice = 3000
print("stock.averagePrice: \(stock.averagePrice)")

출력 결과

Stock(averagePrice: 2300, quantity: 3)
stock.purchasePrice: 6900
stock.averagePrice: 1000




프로퍼티 옵저버

프로퍼티의 값의 변화를 관찰하고 반영한다.
새로운 값이 기존 값과 같더라도 프로퍼티 옵저버가 호출이 된다.(set 될 경우 호출)
저장 프로퍼티, override된 저장 계산 프로퍼티에서만 사용 가능하다.

class Account {
    var credit: Int = 0 {
        // 소괄호 이름 지정
        willSet {   // 값이 저장되기 직전에 호출
            print("잔액이 \(credit)원에서 \(newValue)원으로 변경될 예정입니다.")
        }
        didSet {    // 값이 저장된 직후에 호출
            print("잔액이 \(oldValue)원에서 \(credit)원으로 변경되었습니다.")
        }
    }
}

var account = Account()
account.credit = 1000

출력 결과

잔액이 0원에서 1000원으로 변경될 예정입니다.
잔액이 0원에서 1000원으로 변경되었습니다.




타입 프로퍼티

타입 프로퍼티란 인스턴스 생성 없이 객체 내 프로퍼티 접근을 가능하게 하는 것을 말한다.
타입 프로퍼티는 저장 프로퍼티와 연산 프로퍼티에서만 사용 가능하다.

struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}

print("SomeStructure.computedTypeProperty: \(SomeStructure.computedTypeProperty)")
print("SomeStructure.storedTypeProperty: \(SomeStructure.storedTypeProperty)")
SomeStructure.storedTypeProperty = "Hello"
print("SomeStructure.storedTypeProperty: \(SomeStructure.storedTypeProperty)")

출력 결과

SomeStructure.computedTypeProperty: 1
SomeStructure.storedTypeProperty: Some value
SomeStructure.storedTypeProperty: Hello

[swift] 10. Initialize (초기화)


초기화란 클래스 구조체 또는 열거형의 인스턴스를 사용하기 위한 준비 과정을 말한다.


사용 방법이다.

init(매개변수: 타입, ...) {
    // 프로퍼티 초기화
    // 인스턴스 생성시 필요한 설정들 해주는 코드 작성
}


(swift) 09. 클래스에서 코드이다.

struct User {
    var nickname: String = "이준혁"
    var age: Int = 0

    init() {
        // 인스턴스가 생성되면 호출
        // 프로퍼티의 초기 값, 필요한 설정 등을 여기서 진행한다.
    }
}

let user = User()




예제

class User {
    var nickname: String
    var age: Int

    // 기본 생성자
    init(nickname: String, age: Int) {
        self.nickname = nickname
        self.age = age
    }

    // 사용자 정의 생성자
    init(age: Int) {
        self.nickname = "김철수"
        self.age = age
    }

    // 인스턴스가 메모리에 해제되기 직전에 호출된다.
    // 종료 전 정리작업을 사용할 경우 사용
    // 클래스에서만 사용 가능
    deinit {
        print("deinit user")
    }
}

var user = User(nickname: "이준혁", age: 22)
print("user.nickname: \(user.nickname)")
print("user.age: \(user.age) \n")

var user2 = User(age: 22)
print("user.nickname: \(user.nickname)")
print("user.age: \(user.age) \n")

var user3 = User(age: 23)
user3 = nil // swift는 인스턴스가 더 이상 필요없다고 판단하면 자동으로 메모리에서 소멸시킨다.

실행 결과

user.nickname: 이준혁
user.age: 22

user.nickname: 김철수
user.age: 22

deinit user

[swift] 09. Class (클래스)


스위프트에는 클래스와 구조체가 있다.

구조체와 클래스는 데이터를 용도에 맞게 프로그래밍 할 때 편리하다. 즉, 사용자 정의 데이터 타입을 만들 수 있다.

구조체는 값 타입이며, 클래스는 참조 타입이라는 차이점을 가지고 있다.

클래스는 다음과 같이 작성할 수 있다.

struct 클래스 이름 {
    프로퍼티와 메서드
}




예제

클래스는 생성자를 만들어야 한다.

class Dog {
    var name: String = ""
    var age: Int = 0

    init() { // 생성자

    }

    func introduce() {
        print("name \(name) age \(age)")
    }
}

var dog = Dog()
dog.name = "사랑이"
dog.age = 7

print("dog.name: \(dog.name)")
print("dog.age: \(dog.age)")

dog.introduce()

출력 결과
``` dog.name: 사랑이 dog.age: 7 name 사랑이 age 7