처음부터 차근차근

Swift 문법 정리 5 본문

프로그래밍/Swift

Swift 문법 정리 5

_soyoung 2021. 10. 8. 00:59
반응형
클래스 메서드(class method)

 

클래스 메서드(class method) == 타입메서드(type method)

 

 

Swift의 메서드에는 두가지가 있다.

  1. 인스턴스 메서드 : 인스턴스가 호출
  2. 클래스 메서드(= 타입 메서드)

이 중 클래스 메서드에 대한 이야기이다.

 

 

클래스 메서드란, 클래스가 호출하는 메서드이다.

func 앞에 classstatic 키워드를 붙여 생성한다.

class와 static 차이점 : class 키워드로 만든 클래스 메서드는 자식 클래스에서 override가 가능하다.

class Plant {
    var name = "rose"
    var isblossom = true
    var color = "red"
    // 인스턴스 메서드
    func printPlantInformation() { 
        print("이름 : \(name)");
        print("꽃이 피는가 : \(isblossom)");
        print("색깔 : \(color)");
    }
    // 클래스 메서드(= 타입메서드)
    class func whatAboutPlants() {
        print("It is beutiful.")
    }
    static func doYouLikeThis() { 
        print("yes!")
    }
}
var plant = Plant()
// 인스턴스 메서드는 인스턴스가 호출
plant.printPlantInformation()
// 클래스 메서드는 클래스가 호출
Plant.whatAboutPlants()
Plant.doYouLikeThis()
//결과 : 이름 : rose
//꽃이 피는가 : true
//색깔 : red
//It is beutiful.
//yes!

 

 

 

 

생성자(initializer)
init() {
}

생성자는 인스턴스를 만들 때 호출되는 것이다.

 

 

 

 

생성자의 종류

 

1. default initializer

기본적으로, 자동으로 만들어지는 생성자이다.

var plant : Plant = Plant() // 이때 호출되는게 default initializer

눈에 보이지 않는다.

사용자가 생성자(init())을 하나라도 만들면 default initializer은 사라져버린다.

 

 

2. designated initializer

클래스 내의 모든 프로퍼티를 초기화하는 생성자이다.

class Plant {
    var name : String
    var isblossom : Bool
    var color : String
    func printPlantInformation() { 
        print("이름 : \(name)");
        print("꽃이 피는가 : \(isblossom)");
        print("색깔 : \(color)");
    }
    // designated initializer
    init(plantName: String, isPlantBlossom: Bool, plantColor: String) {
        name = plantName
        isblossom = isPlantBlossom
        color = plantColor
    }
}
var plant : Plant = Plant(plantName: "sunflower", isPlantBlossom: true, plantColor: "yellow")
plant.printPlantInformation()
//결과 : 이름 : sunflower
//꽃이 피는가 : true
//색깔 : yellow

생성자(initializer)가 있으면 저장 프로퍼티의 초기 값을 생략해도 된다.

대신 옆에 자료형을 꼭 적어줘야 한다.

 

 

 

 

생성자 overloading

 

메소드 오버로딩 : 같은 이름의 함수를 여러개 만드는 것

대신 매개변수의 개수나 매개변수의 자료형이나 리턴형을 달리 해줘야한다.

메소드 오버로딩 처럼 생성자도 오버로딩 될 수 있다.

생성자 중첩이란 생성자를 여러개 만드는 것으로, 매개변수의 개수나 매개변수의 자료형을 다르게 해야한다.

 

예시

class Plant {
    var name : String 
    var isblossom : Bool = true
    var color : String = "yellow"
    
    func printPlantInformation() { 
        print("이름 : \(name)")
        print("꽃이 피는가 : \(isblossom)")
        print("색깔 : \(color)")
    }
    
    init(name: String, isblossom: Bool, color: String) {
        self.name = name
        self.isblossom = isblossom
        self.color = color  
    }
    // 생성자 중첩
    init(name: String) {
        self.name = name
    }
}
var plant1 = Plant(name: "catus", isblossom: true, color: "green")
var plant2 = Plant(name: "dandelion")
plant1.printPlantInformation()
print("----------")
plant2.printPlantInformation()
//결과 : 이름 : catus
//꽃이 피는가 : true
//색깔 : green
//----------
//이름 : dandelion
//꽃이 피는가 : true
//색깔 : yellow

 

 

 

 

self

 

'자기 자신'을 나타내는 것으로, 현재 클래스 내의 프로퍼티나 메서드를 가리킬 때 사용한다.

init(name: String, isblossom: Bool, color: String) {
    self.name = name
    self.isblossom = isblossom
    self.color = color
}

 

 

 

 

computed property(계산 프로퍼티)

 

computed property == 계산 프로퍼티 == 연산 프로퍼티

 

Swift의 프로퍼티의 종류에는 두 가지가 있다.

  1. stored property(저장 프로퍼티) : 클래스 내의 변수
  2. computed property(계산 프로퍼티)

이중 computed property에 대한 이야기이다.

 

 

computed property란 stored property를 이용해 값을 리턴하고, stored property의 값을 바꾸는(새로 대입하는) 프로퍼티이다.

computed property에는 gettersetter가 있다.

getter에서는 stored property를 이용해 자신의 값을 리턴하고, 

setter에서는 stored property의 값을 변경한다.

 

computed property를 쓰는 방법에는

1. getter만 쓰거나

2. getter, setter을 다 쓰거나

가 있다.

(setter은 getter없이 쓰지 못함!)

 

첫 번째. getter만 쓰는 경우

class Plant {
    var age : Int
    // computed property 
    var ageSub10 : Int {
        // getter
        get {
            return age - 10
        }
    }
   
    func printPlantAge() { 
        print("식물의 나이 : \(age)")
        print("식물 나이 - 10 : \(ageSub10)")
    }
    
    init(age: Int) {
        self.age = age
    }
}
var plant = Plant(age: 30)
plant.printPlantAge()
//결과 : 식물의 나이 : 30
//식물 나이 - 10 : 30

setter가 없는 경우는 get{}을 생략할 수 있다. 

즉, 아래의 코드도 가능하다.

var ageSub10 : Int {
    return age - 10
}

 

 

두 번째. setter, getter 둘 다 쓰는 경우

 

class Plant {
    var age : Int
    // computed property 
    var ageSub10 : Int {
        //getter
        get {
            return age - 10
        }
        //setter
        set(newValue) {
            age = newValue
        }
    }
   
    func printPlantAge() { 
        print("식물의 나이 : \(age)")
        print("식물 나이 - 10 : \(ageSub10)")
    }
    
    init(age: Int) {
        self.age = age
    }
}
var plant = Plant(age: 30)
plant.printPlantAge()
//결과 : 식물의 나이 : 30
//식물 나이 - 10 : 30

setter가 있으면 get{}을 생략할 수 없다.

매개변수 명은 newValue가 기본이다.

setter의 매개변수 명이 newValue인 경우에는 (newValue)를 생략할 수 있다.

즉, 아래 코드와 같이 쓸 수 있다는 것이다.

var ageSub10 : Int {
    get {
        return age - 10
    }
    set {
        age = newValue
    }
}

 

 

 

 

Failable Initializer
init?{
}
init!{
}

failable Initializer란, 실패 가능한 생성자이다.

인스턴스를 만들 때 인스턴스 생성하는 것을 실패하면 nil을 반환하고,

성공하면 옵셔널형으로 인스턴스를 반환한다.

그래서 항상 return nil구문을 포함하고 있어야 한다.

 

예시

class Plant {
    var age : Int
   
    func printPlantAge() { 
        print("식물의 나이 : \(age)")
    }
    
    init?(age: Int) {
        if age < 0 || age > 1000 {
            return nil
        }
        else {
        	self.age = age
        }
    }
}

 

 

 

 

Failable Initializer로 인스턴스 생성하는 방법

 

failable Initializer로 인스턴스를 생성하면 옵셔널 형의 인스턴스가 반환된다.

옵셔널 형이기 때문에 옵셔널을 풀어줘야 하는데, 그래서 인스턴스를 생성하고 사용하는 방법이 다양하다.

 

1. 옵셔널형으로 인스턴스 생성해서 옵셔널 바인딩하기

class Plant {
    var age : Int
   
    func printPlantAge() { 
        print("식물의 나이 : \(age)")
    }
    
    init?(age: Int) {
        if age < 0 || age > 1000 {
            return nil
        }
        else {
        	self.age = age
        }
    }
}
// Optional형으로 인스턴스 생성
var plant : Plant? = Plant(age: 10)
// 옵셔널 바인딩으로 옵셔널 풀기
if let plantIns = plant {
    plantIns.printPlantAge()
}
else {
    print("인스턴스 생성 실패!")
}
//결과 : 식물의 나이 : 10

 

2. 인스턴스를 생성함과 동시에 옵셔널 바인딩

class Plant {
    var age : Int
   
    func printPlantAge() { 
        print("식물의 나이 : \(age)")
    }
    
    init?(age: Int) {
        if age < 0 || age > 1000 {
            return nil
        }
        else {
        	self.age = age
        }
    }
}
// 인스턴스 생성과 동시에 옵셔널 바인딩
if let plantIns = Plant(age: 10) {
    plantIns.printPlantAge()
}
else {
    print("인스턴스 생성 실패!")
}
//결과 : 식물의 나이 : 10

 

3. 인스턴스 생성과 동시에 강제 언래핑

이 방법은 위험한 방법이다.

인스턴스 생성에 실패해서 nil이 반환되면 그대로 error(crash)가 난다.

class Plant {
    var age : Int
   
    func printPlantAge() { 
        print("식물의 나이 : \(age)")
    }
    
    init?(age: Int) {
        if age < 0 || age > 1000 {
            return nil
        }
        else {
        	self.age = age
        }
    }
}
// 인스턴스 생성과 동시에 강제 언래핑
var plant : Plant = Plant(age: 10)!
plant.printPlantAge()
//결과 : 식물의 나이 : 10

 

4. 인스턴스를 사용과 동시에 강제 언래핑

3번 방법과 마찬가지로 위험한 방법이다.

nil이 반환되면 error가 생긴다.

class Plant {
    var age : Int
   
    func printPlantAge() { 
        print("식물의 나이 : \(age)")
    }
    
    init?(age: Int) {
        if age < 0 || age > 1000 {
            return nil
        }
        else {
            self.age = age
        }
    }
}
// 인스턴스 사용과 동시에 강제 언래핑
var plant : Plant? = Plant(age: 10)
plant!.printPlantAge()
//결과 : 식물의 나이 : 10

 

 

 

 

상속
class 자식클래스 : 부모클래스 {
}

상속이란, 부모 클래스의 내용을 자식 클래스가 물려받는 것이다.부모 클래스를 상속한 자식 클래스는 부모의 모든 기능을 물려받아서 마치 자기 것처럼 마음대로 사용할 수 있다.Swift에서 다중 상속은 불가능하며, 단일 상속만 가능하다.

 

예시

class Plant {
    var age : Int
   
    func printPlantAge() { 
        print("식물의 나이 : \(age)")
    }
    
    init(age: Int) {
        self.age = age
    }
}
// Plant를 상속
class Rose : Plant {
// 눈에는 보이지 않지만 부모 클래스의 모든 기능을 가지고 있음
}
var rose = Rose(age: 1)
rose.printPlantAge()
//결과 : 식물의 나이 : 1

 

 

자식 클래스의 인스턴스를 생성할 때 내부적으로 부모 클래스의 생성자가 먼저 호출된다.

그렇기 때문에 자식클래스의 인스턴스를 생성할 때는 꼭 부모 클래스의 생성자를 호출해줘야 한다.

부모 클래스의 프로퍼티나 메서드, 생성자로 접근하는 키워드는 super이다.

예시

class Plant {
    var age : Int
   
    func printPlantAge() { 
        print("식물의 나이 : \(age)")
    }
    
    init(age: Int) {
        self.age = age
    }
}

class Rose : Plant {
    var name : String
    
    func printAgeName() {
    	print("나이 : \(age)\n이름 : \(name)")
    }
    
    init(name: String, age: Int) {
    	self.name = name
        // 부모 클래스 생성자 호출
        // 매개변수로 들어온 age를 다시 매개변수로 넘긴다.
        super.init(age: age)
    }
}
var rose = Rose(name: "rose", age: 1)
rose.printAgeName()
//결과 : 나이 : 1
//이름 : rose

 

 

 

 

override

 

override란, 부모 클래스의 메서드를 자식 클래스가 재정의하는 것이다.

부모 클래스와 자식 클래스가 서로 같은 메서드를 가지고 있으면 자식 클래스 메서드를 우선으로 한다.

재정의하는 메서드 앞에는 override 키워드를 꼭 써줘야 한다.

class Plant {
    var age : Int
   
    func printPlant() { 
        print("식물의 나이 : \(age)")
    }
    
    init(age: Int) {
        self.age = age
    }
}

class Rose : Plant {
    var name : String
    // method overriding
    override func printPlant() {
    	print("나이 : \(age)\n이름 : \(name)")
    }
    
    init(name: String, age: Int) {
    	self.name = name
        super.init(age: age)
    }
}
var rose = Rose(name: "rose", age: 1)
rose.printPlant()
//결과 : 나이 : 1
//이름 : rose

 

 

 

 

 

 

 

출처 : iOS프로그래밍기초(21-2학기)한성현교수 강의 내용 변형 및 요약

 

 

반응형

'프로그래밍 > Swift' 카테고리의 다른 글

Swift 문법 정리 6  (0) 2021.10.16
Swift 실습 6  (0) 2021.10.15
Swift 실습 5  (0) 2021.10.07
Swift 문법 정리 4  (0) 2021.09.30
Switf 실습 4  (0) 2021.09.30
Comments