2.5 Classes and Inheritance

Joohyun·2022년 4월 7일
0

Class

  • Structure와 유사한 방식으로 선언하고 사용한다.

  • 바뀌지 않는 property는 constant로 선언한다.

class Person {
	// property
	let name: String
    
    // initializer
    init(name: String) {
    	self.name = name
    }
    
    // method
    func sayHello() {
    	print("Hello, there!")
    }
}
let person = Person(name: "Joohyun")
print(person.name) // "Joohyun"
person.sayHello() // "Hello, there!"

Inheritance

  • Structure와 다르게 Class들은 계급적인 관계를 갖는다.

  • superclass(parent class)의 상속을 받는 클래스를 subclass(child class)라고 한다.

1. Base Class 생성

  • base class: superclass가 없는 최상위 클래스를 뜻한다.
  • 가장 일반적인 특징들을 property, method를 통해 정의한다.
// base class인 Vehicle class를 정의한다.
class Vehicle {
	var currentSpeed = 0.0
    
    // computed property
    var description: String {
    	"\(currentSpeed) mile/h"
    }
    
    func makeNoise() {
    	// subclass에서 정의 
   	}
}
let someVehicle = Vehicle()
print("Vehicle: \(someVehicle.description)") // "Vehicle: 0.0 mile/h"

2. Subclass 생성

  • Subclassing: 이미 존재하는 class를 기반으로 새로운 class가 동작하는 것

  • superclass로부터 property와 method들을 상속받는다.

  • subclass에 새로운 property, method를 정의할 수도 있다.

// superclass: Vehicle
// subclass: Bicycle
class Bicycle: Vehicle {
	var hasBasket = false
let bicycle = Bicycle()

// class를 변수, 상수에 할당하면 값이 존재하는 주소가 저장된다.
// bicycle에는 instance의 주소가 저장되어 있기 때문에, constant일지라도 instance 내부의 값을 변경할 수 있다.
bicycle.hasBasket = true

bicycle.currentSpeed = 15.0
print("Bicycle: \(bicycle.description)") // "Bicycle: 15.0 mile/h"

3. Methods, Properties 재정의

  • override키워드를 통해 상속받은 property, method를 재정의하거나 구체화할 수 있다.
class Train: Vehicle {
	// override method
	override func makeNoise() {
    	print("Choo Choo!")
    }
}

let train = Train()
train.makeNoise() // "Choo Choo!"
  • super 키워드를 통해 superclass에 접근할 수 있다.
class Car: Vehicle {
	var gear = 1
    
    // override computed property
    override var description: String {
    	// Vehicle의 description property에 접근
    	super.description + ", \(gear) gear"
    }
}

let car = Car()
car.currentSpeed = 25.0
car.gear = 3
print("Car: \(car.description)") // "Car: 25.0 mile/h, 3 gear"

4. Initializer 재정의

  • structure와 달리 class는 Swift가 자동으로 Memberwise Initializer를 생성해주지 않는다.
  • 그러므로 instance의 모든 property가 초기값을 가지도록 default 값을 설정해주거나, Memberwise Initializer를 정의해주어야 한다.
// superclass
class Person {
	let name: String
    
    init(name: String) {
    	self.name = name
    }
}
  • superclass의 initializer에 접근하는 super.init() 키워드를 사용하여 subclass의 initializer를 간단히 정의할 수 있다.
// subclass
class Student: Person {
	var favoriteSubject: String
    
    init(name: String, favoriteSubject: String) {
    	self.favoriteSubject = favoriteSubject
        
        // Person의 Initializer 
        super.init(name: name)
    }
}

References

  • structure와 달리 class는 instance를 constant, variable에 할당 시, 해당 instance가 저장되어 있는 주소가 할당된다.

Structure VS Class

  • Structure
    - 변수 또는 상수에 값(value) 저장

    - 한 변수의 instance property가 변경되어도, 나머지 변수들은 영향을 받지 않는다.

    struct Person {
    	var name: String
        var age: Int
    }
    
    var jack = Person(name:Jack, age: 24)
    		var myFriend = jack
    
    jack.age += 1
    
    print(jack.age) // 25
    print(myFriend.age) // 24
  • Class
    - 변수 또는 상수에 주소(reference) 저장

    - 한 변수 또는 상수의 instance property가 변경되면, 해당 instance를 참조하는 나머지 변수들 모두 영향을 받는다.

    class Person {
        let name: String
        var age: Int
    
        init(name: String, age: Int) {
            self.name = name
            self.age = age
        }
    }
    // jack과 myFriend에는 동일한 instance의 주소가 할당된다.
    var jack = Person(name:Jack, age: 24)
    var myFriend = jack
    
    // 주소에 저장되어 있는 instance의 prperty값을 변경한다.
    jack.age += 1
    
    print(jack.age) // 25
    
    // 값이 아닌 주소가 저장되어 있으므로
    print(myFriend.age) // 25

Structure 대신 Class를 써야 하는 경우

  • class의 특징이 필요하지 않은 대부분의 경우에는 structure를 사용해 type을 생성한다.

  • 하지만, 아래와 같은 특별한 경우에는 class를 사용한다.

1. class를 사용하는 framework 이용

  • Foundation, UIKit와 같은 framework는 base class만 선언이 되어있으므로, class를 이용해 직접 subclass를 작성하여야만 한다.

    ex) UIKit를 통해 custom view를 만들고 싶을 때, UIView의 subclass를 생성해야 한다.

  • framework의 method들은 class instance를 매개변수로 가지는 경우가 많다.

    (class는 주소를 저장하기 때문에 의미가 있다.)

2. Stable Identity 특징 활용

  • 다양한 위치에서 하나의 instance를 이용할 때, class를 사용하면 편리하다.

    (해당 instance를 constant 또는 variable에 할당 시 주소값이 저장되므로 모두 동일한 값을 보장한다.)

    예시) MessageCell

    • UITableViewCell class는 table view에서 메세지에 대한 정보를 보여주는 MessageCell이라는 subclass를 가진다.

      class MessageCell: UITableViewCell {
      
      	// `UITableViewCell`에서 메세지에 대한 정보를 가진 property를 업데이트
      	func update(message: Message) {
          	textLabel.text = message.subject
              detailTextLabel.text = message.previewText
          }
      }
    • update(message:)를 통해 cell이 수정되어도, cellForRow(at: IndexPath)의 cell 역시 같은 값으로 수정된다.

    • 만약 structure였다면 update함수를 통해 cell을 아무리 수정하여도 cell의 원본은 변경되지 않을 것이다.

      // cellForRow(at: IndexPath) : able view의 내용이 보여지기 직전에 호출되어 각 cell에 올바른 내용이 위치하도록 한다.
      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      	
          // cell instance 생성하여 메모리에 삽입
      	let cell = MessageCell(style: .default, reuseIdentifier: "MessageCell")
          // cell 주소를 매개변수로 update(message:) 함수 호출
          cell.update(message: message)
          
          // cell 주소 return
          return cell
      }
    • 매개변수로 tableView, cell의 주소가 들어간다.

      // 유저가 스크롤을 움직이면 호출됨
      override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
      	// 사용자 정의
      }

Excerpt From
Develop in Swift Fundamentals
Apple Education
https://books.apple.com/kr/book/develop-in-swift-fundamentals/id1581182804?l=en
This material may be protected by copyright.

profile
Developer

0개의 댓글