swift 기초 - 상속, 인스턴스의 생성과 소멸
[1] 상속
스위프트의 상속은 클래스, 프로토콜 등에서 가능하다.
열거형, 구조체는 상속이 불가능하다.
스위프트는 다중상속을 지원하지 않는다.
클래스의 상속과 재정의
class 이름 : 상속받을 클래스 이름 {
//구현부
}
[1-1] 클래스 정의
class Person {
//[1] 인스턴스 변수
var name : String = ""
//[2] 인스턴스 메소드
func selfIntroduce(){
print("저는 \(name) 입니다.")
}
//[2] 인스턴스 메소드 2
//final 키워드 - 재정의 방지
final func sayHello(){
print("hello")
}
//[3] 타입 메서드
//재정의 불가 타입 메서드 - static
static func typeMethod(){
print("type method - static!")
}
//[4] 재정의 가능 타입 메서드 - class
class func classMethod() {
print("type method - class!")
}
//[5] 재정의 가능한 class 메서드라도
//final 키워드를 사용하면 재정의 할 수 없다.
//메서드 앞의 static 과 final class 는 똑같은 역할을 한다.
final class func finalClassMethod(){
print("type method - final class")
}
}
[1-2] 서브 클래스 정의
class Student: Person {
//인스턴스 변수
var major : String = ""
//오버라이드 - 1
override func selfIntroduce() {
print("저는 \(name)이고 , 전공은 \(major) 입니다.")
}
//오버라이드 - 2
override class func classMethod() {
print("overriden type method - class")
}
!주의 [1] : "static" 을 사용한 타입 메서드는 재정의 할 수 없습니다.
//Cannot override static method
//override static func typeMethod(){}
!주의 [2] : "final" 키워드를 사용한 메소드, 프로퍼티는 재정의 할 수 없습니다.
//override func sayHello() { }
//override class func finalClassMethod() { }
[1-3] 사용하기
//인스턴스 변수 생성
let person : Person = Person()
let kim : Student = Student()
//대입
person.name = "gildong"
kim.name = "kimdongsoo"
kim.major = "swift"
//인스턴스 객체로 인스턴스 메소드 호출
person.selfIntroduce() //저는 gildong 입니다.
kim.selfIntroduce() //저는 kimdongsoo이고 , 전공은 swift 입니다.
//슈퍼클래스(부모 클래스)로 타입 메소드 호출
Person.classMethod() //type method - class!
Person.typeMethod() //type method - static!
Person.finalClassMethod() //type method - final class
//서브클래스 (자식클래스)로 부모의 타입 메소드 호출
Student.classMethod() //overriden type method - class
Student.typeMethod() //type method - static!
Student.finalClassMethod() //type method - final class
[2] 인스턴스의 생성과 소멸
이니셜라이저와 디이니셜라이저 (init, deinit)
스위프트의 모든 인스턴스는 초기화와 동시에 모든 프로퍼티에 유효한 값이 할당되어 있어야 한다.
프로퍼티에 미리 기본값을 할당해 두면, 인스턴스가 생서됨과 동시에 초기값을 지니게 된다.
[2-1] 기본값이 있는 클래스
class PersonA {
//모든 저장 프로퍼티에 기본값 할당
var name : String = "unknown"
var age : Int = 0
var nickName : String = "nick"
}
let park : PersonA = PersonA()
park.name = "park"
park.age = 30
park.nickName = "hopark"
[2-2] 이니셜라이저
프로퍼티 기본값을 지정하기 어려운 경우,
이니셜라이저를 통해서 인스턴스가 가져야 할 초기값을 전달 할 수 있다.
class PersonB {
//기본값이 없는 인스턴스 변수
var name : String
var age : Int
var nickName : String
//이니셜 라이저
init(name: String, age: Int, nickName: String) {
self.name = name
self.age = age
self.nickName = nickName
}
}
let huang:PersonB = PersonB(name: "huangkyo", age: 20, nickName: "황닉")
//nil 할당시 오류!
//let huang2:PersonB = PersonB(name: "huangkyo", age: 20, nickName: nil)
[2-3] 프로퍼티의 초기값이 꼭 필요 없을때 - 옵셔널 사용
class PersonC {
//기본값이 없는 인스턴스 변수 - init 메소드를 반드시 써줘야 에러가 안난다!
var name : String
var age : Int
//옵셔널 사용
var nickName : String?
//이니셜 라이저 - 1
init(name: String, age: Int, nickName: String) {
self.name = name
self.age = age
self.nickName = nickName
}
//이니셜 라이저 - 2
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let jenny: PersonC = PersonC(name: "jenny", age: 10)
let mike: PersonC = PersonC(name: "mike", age: 15, nickName: "m")
[2-4] 암시적 추출 옵셔널
인스턴스 사용에 꼭 필요하지만
초기값을 할당하지 않고자 할 때 사용
class Puppy {
//name 변수에 원래 값이 없으면 안된다 : Class 'Puppy' has no initializers
var name: String //강아지 이름
var owner: PersonC! //주인 객체
init(name: String) {
self.name = name
}
func goOut() {
print("\(name)가 주인 \(owner.name)와 산책을 합니다.")
}
}
let happy : Puppy = Puppy(name: "happy")
//강아지는 주인없이 산책할 수 없다.
//happy.goOut() //오류발생
happy.owner = jenny
happy.goOut()
//happy가 주인 jenny와 산책을 합니다.
[2-5] 실패 가능한 이니셜라이저
이니셜라이저 매개변수로 전달되는 초기값이 잘못된경우
인스턴스 생성에 실패할 수 있다
인스턴스 생성에 실패하면 nil을 반환한다.
그래서 실패 가능한 이니셜라이저의 반환 타입은 옵셔널이다.
class PersonD {
var name:String
var age:Int
var nickName: String?
//초기화 하기전에 값 검증
init?(name: String , age:Int){
if (0...120).contains(age) == false {
return nil
}
if name.count == 0 {
return nil
}
self.name = name
self.age = age
}
}
//옵셔널 타입으로 작성해야됨
//Value of optional type 'PersonD?' must be unwrapped to a value of type 'PersonD'
//let jhonadan1 : PersonD = PersonD(name: "jhonadan", age: 23)
let jhonadan2 : PersonD? = PersonD(name: "jhonadan", age: 23)
//오류 - age 223 이다...
//let jhonadan : PersonD? = PersonD(name: "jhonadan", age: 223)
[2-6] 디이니셜라이저
deinit은 클래스의 인스턴스가 메모리에서 해제되는 시점에 호출된다.
인스턴스가 해제되는 시점에 해야될 일을 구현할 수 있다.
class PersonE {
//기본값이 없는 인스턴스 변수 - init 메소드를 반드시 써줘야 에러가 안난다!
var name : String
var pet : Puppy?
var chaild:PersonC
//매개변수 : 주인이름 , 자식객체
init(name: String, chaild: PersonC) {
self.name = name
self.chaild = chaild
}
//메모리에서 해제될 시점에 호출됨
deinit {
if let petName = pet?.name {
print("\(name)가 \(chaild.name)에게 \(petName)을 인도합니다.")
self.pet?.owner = chaild
}
}
}
//var donald:PersonE = PersonE(name: :"donald", chaild: jenny)
//개 주인 객체 생성
var donald:PersonE? = PersonE(name: "donald", chaild: jenny)
donald?.pet = happy
donald = nil // donald 인스턴스가 더이상 필요없으므로 메모리에서 해제됩니다
//donald가 jenny에게 happy을 인도합니다.
참고
'아이폰 개발 > Swift' 카테고리의 다른 글
[스탠포드]Swift 강좌 - ios 구조 (0) | 2021.03.09 |
---|---|
swift 기초 - assert , guard , protocol (1) | 2021.03.05 |
swift 기초 - 옵셔널 체이닝, 타입캐스팅 (0) | 2021.03.05 |
swift 기초 - 클로저 , 프로퍼티, 프로퍼티 감시자 (0) | 2021.03.04 |
swift 기초 - 옵셔널, 구조체, 클래스, 열거형, 값타입 참조타입 (0) | 2021.03.03 |