/**
클래스
상속(Inheritance) 과 초기화(Initialization)
*/
// 1. 상속의 재정의
class Person { // 부모 클래스, super 클래스, 상위 클래스
var id = 0
var name = "이름"
var email = "abc@gmail.com"
}
class Student: Person { // 자식 클래스, Sub 클래스, 하위 클래스
// id
// name
// email
var studentId = 0
}
class Undergraduate: Student {
// id
// name
// email
//studentId
var major = "전공"
}
/**
클래스의 상속과 초기화
1. 클래스의 상속
- 상속은 유일하게 클래스에서만 지원하는 기능(구조체는 상속 불가능)
- 본질적으로 성격이 비슷한 타입을 새로 만들 때
*/
class AClass {
final var name = "이름" // final 을 붙이면 해당 속성은 재정의가 불가능 의미
}
final class BClass: AClass { // final 을 붙이면 더 이상 상속을 할 수 없음을 의미
var id = 0
}
let b = BClass()
b.name
/*
BClass 는 AClass를 상속해서 구현
서브클래스는 슈퍼클래스로부터 멤버를 상속함
클래스의 상속 금지의 키워드 final
(경우에 따라서, 클래스의 상속을 금지해야하는 경우가 있음)
(final 를 각 멤버 앞에 붙인 경우, 해당 멤버 재정의 불가라는 뜻)
*/
/**
상위 클래스에서 존재하는 멤버를 변형하는 것을 재정의라고 함
재정의를 하려는 멤버에는 override 키워드를 붙여야함 (자세한 내용은 다음 강의에서 다룰 예정)
*/
/**
UIKit 의 상속 구조
- 애플이 미리 만들어 놓은 UIKit 에서는 상속의 구조가 세밀하고 복잡하게 만들어져 있음
- 상속의 구조를 외울 필요는 없고, 대량적인 내용만 이해하면 됨 ====> 프레임워크 강의에서 자세하게 설명 예정
*/
/**
2. 재정의(Overriding)
- 재정의
- 서브클래스에서 슈퍼클래스의 동일한 멤버를 변형하여 구현
- 재정의 가능한 대상(멤버)
- 속성 (하지만, 저장 속성에 대한 재정의는 어떠한 경우에도 불가능)
- 메서드 (메서드, 서브스크립트, 생성자)
==> 속성과 메서드는 재정의 방식이 다름
*/
class Aclass { // 부모 클래스
func doSomething() {
print("Do something")
}
}
class Bclass: Aclass { // 자식 클래스
override func doSomething() { // 함수를 재정의 함.
super.doSomething() // 슈퍼클래스에 있는 메서드를 실행함.
print("Do something. Do another job")
}
}
var bclass = Bclass()
bclass.doSomething()
// Do something
// Do something. Do another job
// 메모리 관점으로 상속은 저장속성을 추가하는 개념 !!
// 메모리 관점으로 메서드는 새로운 주소를 추가하는 개념 !!
/**
재정의 (Orverriding) 의 기본 문법
*/
class SomeSuperclass {
var aValue = 0
func doSomething() {
print("Do something")
}
}
class SomeSubclass: SomeSuperclass {
// 저장속성의 재정의는 원칙적 불가
// override var aValue = 3
// 저장속성 ==> (재정의) 계산속성
// 그러나, 메서드 형태로 부수적 추가는 가능
override var aValue: Int {
get {
return super.aValue
}
set { // salf 로 쓰면 안됨.
super.aValue = newValue
}
}
override func doSomething() {
super.doSomething()
print("Do something 2")
}
}
var ssc = SomeSubclass()
ssc.aValue
ssc.aValue = 5
ssc.aValue
ssc.doSomething()
// 2-2. 재정의 예시
// 1. 속성의 재정의(엄격)
class Vehicle {
var currentSpeed = 0.0
var halfSpeed: Double {
get {
return currentSpeed / 2
}
set {
currentSpeed = newValue * 2
}
}
}
class Bicycle: Vehicle {
// 저장 속성 추가는 당연히 가능
var hasBasket = false
// 1. 저장속성 ===> 계산속성으로 재정의(메서드 추가) 가능
override var currentSpeed: Double {
// 상위 속성이기 때문에 super 키워드 필요
get {
return super.currentSpeed
}
set {
super.currentSpeed = newValue
}
}
// 2. 저장속성 ===> 속성감시자를 추가하는 재정의(메서드 추가는 가능)
// override var currentSpeed: Double {
//
// willSet {
// print("값이 \(currentSpeed) 에서 \(newValue) 로 변경 예정")
// }
// didSet {
// print("값이 \(oldValue) 에서 \(currentSpeed) 로 변경 예정")
// }
// }
// 3. 계산속성을 재정의 가능 (super 키워드 주의)
// override var halfSpeed: Double {
// get {
// return super.currentSpeed / 2
// }
// set {
// super.currentSpeed = newValue * 2
// }
// }
// 4. 계산속성을 재정의 하면서, 속성감시자 추가 가능 (속성감시자 부분 참고) - 예외적인 상황
// override var halfSpeed: Double {
// willSet {
// print("값이 \(halfSpeed) 에서 \(newValue) 로 변경 예정")
// }
// didSet {
// print("값이 \(oldValue) 에서 \(halfSpeed) 로 변경 예정")
// }
// }
}
// 2. 메서드의 재정의
class Vehicle1 {
var currentSpeed = 0.0
var datas = ["1","2","3","4","5"]
func makeNoise() {
print("경적을 울린다.")
}
subscript(index: Int) -> String {
get {
if index > 4 {
return "0"
}
return datas[index]
}
set {
datas[index] = newValue
}
}
}
// 메서드의 재정의 방식
class Bicycle1: Vehicle1 {
// 1. 상위 => 하위 호출 (가능)
override func makeNoise() {
super.makeNoise()
print("자전거가 지나간다고 소리친다.")
}
// 2. 하위 => 상위 호출 (가능)
// override func makeNoise() {
// print("자전거가 지나간다고 소리친다.")
// super.makeNoise()
// }
// 3. 상위구현 아예 무시 (가능)
// override func makeNoise() {
// print("자전거가 지나간다고 소리친다.")
// }
// 4. 서브스크립트도 재정의 가능
override subscript(index: Int) -> String {
get {
if index > 4 {
return "777"
}
return super[index]
}
set {
super[index] = newValue
}
}
}
let v = Bicycle1()
v[6]
v.currentSpeed
v.makeNoise()