이전 포스팅

인스턴스 메서드

  • 인스턴스 메서드는 함수랑 유일하게 다른점 클래스나 구조체 내부에 소속된 것외에는 똑같다. 매개변수를 받을수 있고, 반환타입도 지정할 수 있고, 내부에서 구문을 또 실행할 수 있다.
  • 다만 인스턴스를 통해 호출을 해야하고, 클래스 내에 정의돈 모든 프로퍼티를 참조할 수 있으면, self 키워드를 사용할 수 있다는게 디테일하게 보면 함수와의 차이점이라고 할 수 있다.
  • 여기서 self. 키워드는 해당 메서드를 호출하는 인스턴스 자신을 뜻하기 때문에, 각각의 인스턴스 마다 같은 메서드를 다른 매개변수를 통해 다르게 결과를 만들수 있다.
  • self를 안써도 그러면 인스턴스 프로퍼티의 참조를 할 수 있을까? 가능하다. swift 컴파일러는 인스턴스 메서드에서는 self를 붙이지 않아도 변수가 프로퍼티라는것을 잘 인지한다. 다만 메서드안에 프로퍼티와 같은 이름을 갖은 변수가 있다면, self를 써줘야한다.
  • 다른 언어에서의 메서드와 큰 차이는 없다. 딱 하나! 구조체나 열거형의 인스턴스 메서드 내부에서 프로퍼티 값을 수정할때 반드시 메서드 앞에 mutating이라는 키워드를 추가해야한다.
struct Point{
	var x = 0.0, var y = 0.0
    mutating func resetXY(){
    	self.x = 0
        self.y = 0
    }
}

var point1 = Point(x:10.0, y: 5.0)
print("point1.X = \(point1.x), point2.Y = \(point1.y) // 출력 10.0, 5.0
point1.resetXY()
print("point1.X = \(point1.x), point2.Y = \(point1.y) // 출력 0.0, 0.0

상속

  • 클래스와 구조체의 차이점이 뭐냐 라고 하면 제일 큰 차이점은 상속(Inheritence)다.
  • 상속은 생각하면 부모가 자식한테 물려주는것이니깐, 클래스로 다시 생각하면, 클래스의 메서드와 프로퍼티르를 물려준다고 생각하고, 그 물림을 받은 자식이 있다고 생각하면 된다.

    프로퍼티와 메서드를 물려준 클래스는 부모, 상위, 슈퍼, 기본 클래스
    프로퍼티와 메서드를 물려받은 클래스는, 자식, 하위, 서브, 파생 클래스

서브클래싱

  • 클래스 A를 상속받아 새로운 클래스를 정의하는것이 서브 클래싱이다. 서브 클래싱은 아래와 같은 양식을 따른다.
class <클래스 이름> : <부모 클래스> {
	// 이외의 내용
}
  • 자식 클래스는 부모 클래스의 있는 메서드와 프로퍼티를 사용,참조할 수 있다. 만약 근데 자식 클래스에서 상속받은 메서드나 프로퍼티의 대한 구현을 재정의 하고 싶다면?

오버라이딩

  • 자식 클래스에서 상위 클래스에서 정의된 메서드나 프로퍼티를 재정의하여, 물려받은 내용을 덮어쓰는것을 오버라이딩 (Overriding)이라고 한다.
  • swift 에서는 오버라이딩을 하기 위해서는 자식 클래스에서 메서드나 프로퍼티 앞에 override 키워드를 사용해야 한다, 해당 키워드를 사용하면, 자식 클래스의 상위 클래스, 즉 부모 클래스, 부모의 부모, 부모의부모의 부모...최상위 클래스까지 다 검사해서, 해당 메서드나 프로퍼티가 있는지 확인한다. 만약에 있다면 문제가 없지만, 만약에 상위 클래스에서 구현이 되지 않은 메서드나 프로퍼티 앞에 override를 사용하면 역시나 오류가 생긴다.

프로퍼티 오버라이딩

  • 프로퍼티를 오버라이딩을 하기 위해선 몇가지 조건이 있다. 아래 조건이 부합하지 않는다면 프로퍼티 오버라이딩은 허용되지 않는다.
    • 저장 프로퍼티를 get,set 구문이 모두 있는 연산 프로퍼티로 오버라이딩 하는것.
    • get,set 구문이 모두 제공되는 연산 프로퍼티를 get,set 구문이 모두 제공되는 연산 프로퍼티로 오버라이딩 하는것
    • get 구문만 제공되는 연산프로퍼티를 get,set 구문이 모두 제공되는 연산프로퍼티로 오버라이딩 하는것.
    • get 구문만 제공되는 연산프로퍼티를 get 구문이 모두 제공되는 연산 프로퍼티로 오버라이딩 하는것.
  • 위에 조건들을 보면 정리를 하자면, 자식 클래스에서는 상위클래스의 저장프로퍼티든 연산프로퍼티든, 최소한 get구문이 포함되어야 하고, 상위클래스에서 get 구문만 제공되는것이 아닌 이상 set 구문까지 포함하는 연산프로퍼티로 오버라이딩을 해야한다.

메서드 오버라이딩

  • 메서드 오버라이딩은 신경 쓸게 많다고 하면 많은 거지만 오히려 더 쉽다. 상위 클래스에서 구현된 메서드를 매개변수, 메서드 이름, 타입, 종류 등등 모든 걸 똑같이 사용해야한다. 즉 메서드 내부적으로는 변경할 수는 있지만, 매서드를 기본 틀은 똑같아야 하는것이다. 만약 이름, 타입, 종류, 매개변수 중 하나라도 틀리면, 새로운 메서드라고 판단되고, 오버라이딩이 아니기 때문에, override 키워드를 사용하지 않아야 한다.
  • 그러면 override를 하고 나서는, 상위 클래스에서 구현한 메서드는 사용하지 못하는것일까? 그건 아니다. super.메서드()를 자식 클래스에서 호출하면 상위 클래스 메서드를 호출하게 된다. 그러면 만약에 바로 위 부모 클래스에서는 override를 하고 super.메서드()를 호출하면? 이건 안된다. 즉 super 키워드는 부모클래스의 메서드를 참조하는것이기 때문에, 만약 그 부모클래스가 override를 했다면, 더 이상위로는 호출 할 수없게 된다.
  • 만약 오버라이딩을 못하게 막구 싶으면 final 키워드를 사용하면 된다. final 키워드는 class 앞에도 붙일 수 있으며, final class Temp{} 하면 Temp class 는 상속 자체가 차단되고, 서브클래싱도 안된다.
class Vehicle {
    var speed = 0.0
    
    var description: String {
        return "시간당 \(self.speed)의 속도로 이동하고 있습니다"
    }
    
    func makeNoise() {
        print("Vehicle : MakeNoise()")
    }
}

class Bike : Vehicle {
    //override var currentSpeed: Double  = 10 
    //오류:  Cannot override with a stored property 'currentSpeed'
    
    override var speed: Double {
        get{
            return 10.0
        }
        set{
            
        }
    }

    override func makeNoise() {
        print("Bike : MakeNoise()")
    }
    
    func makeNoiseFromParent(){
        super.makeNoise()
    }
    
}

let bk = Bike()
bk.makeNoise()
// 출력 : Bike : MakeNoise()
bk.makeNoiseFromParent()
// 출력 : Vehicle : MakeNoise()
bk.description()
// 출력 : "시간당 10.0의 속도로 이동하고 있습니다"
profile
개발자 (진)

0개의 댓글