본문 바로가기

iOS 관련 공부

속성(Property)과 메서드(Method) - 2

메서드(Method)

인스턴스 메서드(Instance Methods)

가장 기본적인 메서드

 

 

구조체의 인스턴스 메서드

값 타입(구조체, 열거형)에서 기본적으로 인스턴스 메서드 내에서 속성을 수정할 수 없음

수정하려면, mutating(변형되는)키워드를 붙이면 속성 수정 가능해짐(클래스와 구조체의 차이)

struct Dog2 {
    var name: String
    var weight: Double
    
    init(name: String, weight: Double) {
        self.name = name
        self.weight = weight
    }
    
    func sit() {
        print("\(name)가 앉았습니다.")
    }
    
    mutating func changeName(newName name: String) {   // mutating 생략 불가
        self.name = name
    }
    
}

mutate: 변형되다 (mutating - 변형되는)

컴파일러가 알아서 수정해줌 (실수에 대한 자동 방지가 되지만, 문법적으로 인지하고 있어야함)

 

스택에 영역에 저장하는 것은 메서드로 바꿀 수 없다 라고 간단히 생각해도 됨

 

 

오버로딩(Overloading)

함수에서의 오버로딩과 동일하게 클래스, 구조체, 열거형의 메서드에서도 오버로딩 지원

 

 

 

타입 메서드 (Type Methods)

메서드이지만, 인스턴스의 성격이 아닌 타입 자체의 성격에 가까운 메서드일 때, 타입메서드로 구현 가능

class Dog {
    static var species = "Dog"
    
    var name: String
    var weight: Double
    
    init(name: String, weight: Double) {
        self.name = name
        self.weight = weight
    }
    
    func sit() {
        print("\(name)가 앉았습니다.")
    }
    
    func trainning() {
        print("월월 저는 \(Dog.species)입니다.")
        sit()
        sit()
        self.sit()
    }
    
    func changeName(newName name: String) {
        self.name = name
    }
    
    static func letmeKnow() {     // 타입 메서드에서, 타입속성에 접근시에는 타입으로 접근하지 않아도 됨
        print("종은 항상 \(species)입니다.")      // Dog.species라고 써도됨. -> 얘 자체가 타입 메서드이기 때문
    }
    
}

 

일반메서드 호출

let bori = Dog(name: "보리", weight: 20.0)
bori.sit()


bori.changeName(newName: "말썽쟁이보리")
bori.sit()

 

타입 메서드의 호출

Dog.letmeKnow()   // "종은 항상 Dog입니다."

타입이름명시.

 

인스턴스 기능이 아닌, 타입 자체에 필요한 기능을 구현할 때 주로 사용

타입 자체가. 가져야 하는 공통된 기능(동작) 구현시

 

타입 메서드 사용 예시

 

Int.random(in: 1...100)

Double.random(in: 1.2...3.7)

 

 

 

클래스 - 타입 메서드의 상속

상속부분 공부 후 다시 볼 것임

타입 메서드를 상속시 재정의 가능 하도록 하려면 -> static 키워드를 상속가능한 class 키워드로 바뀌어야 함

// 상위클래스

class SomeClass {
    class func someTypeMethod() {     // 타입 메서드 / static일때는 재정의 불가
        print("타입과 관련된 공통된 기능의 구현")
    }
}

SomeClass.someTypeMethod()



// 상속한 서브클래스

class SomeThingClass: SomeClass {
    override class func someTypeMethod() {
        //super.someTypeMethod()
        print("타입과 관련된 공통된 기능의 구현(업그레이드)")
    }
}

SomeThingClass.someTypeMethod()

 

class - 상속시 재정의 가능 키워드

static 키워드로 선언하면 (상속시)재정의 불가 (상속이 불가한 것 아님)

 

 

서브스크립트(Subscripts) 

대괄호를 이용해서 접근가능하도록 만든 문법을 가르킨다.

 

 - 배열

   array[인덱스]

 

 - 딕셔너리

   dictionary[]

 

대괄호는 사실 특별한 형태의 메서드(기능) 호출 역할 -> 메서드를 직접 구현도 가능

var array = ["Apple", "Swift", "iOS", "Hello"]

array[0]  // "Apple"
array[1]  // "Swift"

내부적으로 대괄호를 사용하면 어떤 값을 리턴하도록 구현이 되어 있어서 가능한 일

 

인스턴스.0

인스턴스.method()  -> 이런 형태가 아닌

 

인스턴스[파라미터]  -> 이런 형태로 동작을 가능하게 한 문법(대괄호로 메서드의 기능을 대신)

 

 

(인스턴스) 서브스크립트(Subscriptes)의 직접 구현 - 클래스, 구조체, (열거형)

 

인스턴스 메서드로써의 서브스크립트 구현

class SomeData {
    var datas = ["Apple", "Swift", "iOS", "Hello"]

    
    subscript(index: Int) -> String {     // 1) 함수와 동일한 형태이지만, 이름은 subscript
        get {                             // 2) get/set은 계산속성에서의 형태와 비슷
            return datas[index]
        }
        set(parameterName) {
            datas[index] = parameterName         // 또는 파라미터 생략하고 newValue로 대체 가능(계산 속성의 setter와 동일)
        }
    }
    
}


var data = SomeData()
data[0]  // get블럭 실행
//data[0] = "AAA"  // set블럭 실행

파라미터 생략 불가(값이 반드시 필요)

리턴형도 생략 불가능(저장할 값의 타입 명시 필요)

 

읽기 전용(read-only)으로 선언 가능 (set블록은 선택적으로 구현이 가능하고, 쓰기 전용으로의 선언은 불가)

 

 

서브스크립트 사용 예시 - 대괄호 형태로 사용하는 메서드

 

struct TimesTable {
    let multiplier: Int = 3
    
    subscript(index: Int) -> Int {   // get만 가능 set구현 X
        return multiplier * index
    }
}


let threeTimesTable = TimesTable()

print("6에 3배를 하면 숫자 \(threeTimesTable[6]) 이(가) 나옵니다.")

threeTimesTable[2]  // 6
struct Matrix {
    // 2차원 배열
    var data = [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"]]
    
    // 2개의 파라미터를 받는 읽기전용 서브스크립트의 구현
    subscript(row: Int, column: Int) -> String? {
        if row >= 3 || column >= 3 {
            return nil
        }
        return data[row][column]
    }
}


// 2개의 파라미터를 받는 서브스크립트 구현도 가능


var mat = Matrix()

mat[0, 1]!     // 대괄호 안에 파라미터 2개 필요

 

 

 

타입 서브스크립트(Type Subscriptes) - 클래스, 구조체, (열거형)

enum Planet: Int {   // 열거형의 원시값
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
    
    static subscript(n: Int) -> Planet {    // Self
        return Planet(rawValue: n)!
    }
}

let mars = Planet[4]      // Planet.venus
print(mars)

 

static 또는 class 키워드로 타입 자체의 서브스크립트 구현 가능

class는 상속시 재정의 가능