210323 Tue

Sunny·2021년 4월 3일
0

Today I Learned

목록 보기
17/88

1. 첫 번째 학습 내용: 프로토콜 (Protocols)

프로토콜이란? 객체의 설계도!

프로토콜은 특정 기능 수행에 필수적인 요수를 청의한 청사진(blueprint)입니다. 프로토콜을 만족시키는 타입을 프로토콜을 따른다(conform)고 말합니다. 프로토콜에 필수 구현을 추가하거나 추가적인 기능을 더하기 위해 프로토콜을 확장(extend)하는 것이 가능합니다.

프로토콜에는 구현해야 할 메소드의 명세가 작성되어 있어서 프로토콜만 보더라도 무엇을 어떻게 호출해야 하는지에 대한 것을 알 수 있음.

1. 프토토콜 문법 (Protocol Syntax)

프로토콜의 정의는 클래스, 구조체, 열거형 등과 유사합니다.

protocol SomeProtocol {
    // protocol definition goes here
}

프로토콜을 따르는 타입을 정의하기 위해서는 타입 이름 뒤에 콜론(:)을 붙이고 따를(Conforming) 프로토콜 이름을 적습니다. 만약 따르는 프로토콜이 여러개라면 콤마(,)로 구분해 줍니다.

struct SomeStructure: FirstProtocol, AnotherProtocol {
    // structure definition goes here
}

서브클래싱인 경우 수퍼클래스를 프로토콜 앞에 적어 줍니다.

class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
    // class definition goes here
}

타입 메소드나 타입 프로퍼티도 프로토콜에 정의할 수 있습니다.

프로토콜의 각 선언 앞에 static 키워드를 붙이면 됩니다.

protocol AnotherProtocol {
    static var someTypeProperty: Int { get set }
}

1.1 프로토콜 프로퍼티

프로토콜에 선언되는 프로퍼티에는 초기값을 할당할 수 없음.

연산 프로퍼티인지 저장 프로퍼티인지 구분하지 않음.

프로퍼티의 종류, 이름, 변수/상수 구분, 타입, 읽기 전용인지 읽고 쓰기가 가능한지에 대해서만 정의할 뿐.

prptocol SomePropertyProtocol {
	var name: String { get set }
	var description: String {get }
}

인스턴스 프로퍼티 두 개를 SomePropertyProtocol 프로토콜에 선언하고 있음.

실제로 내용을 선언한 것이 아니라 이러한 종류의 프로퍼티가 선언될 것이라고 설명하는 의미.

프로퍼티의 명세에는 읽기 전용/ 읽고 쓰기에 대한 여부를 get과 set 키워드로 표시.

→ 읽기 전용으로 설정: get

→ 읽고 쓰기가 모두 가능한 프로퍼티를 선언하고자 할 때는 get과 set 모두 작성

struct Member: SomePropertyProtocol {
	var name = "Sunny"
	var description: String {
		return "Name : \(self.name)"
	}
}

1.2 프로토콜 메소드

protocol SomeMethodProtocol {
	func execute(input: String)
	func showPort(p: Int) -> String
}
struct Serice: SomeMethodProtocol {
	func execute(input: String) {
		if input == "start" {
			print("실행합니다")	
		}
	}

	func showPort(p: Int) -> String {
		return "Port : \(p)"  
	}
}

변경 가능한 메소드 요구사항 (Mutating Method Requirements)

  • mutating 키워드를 사용해 인스턴스에서 변경 가능하다는 것을 표시할 수 있습니다.
  • 이 mutating 키워드는 값타입 형에만 사용합니다.
  • 프로토콜에 mutating을 명시한 경우 이 프로토콜을 따르는 클래스 형을 구현할 때는 메소드에 mutating을 명시하지 않아도 됩니다.
protocol Togglable {
    mutating func toggle()
}
enum OnOffSwitch: Togglable {
    case off, on
    mutating func toggle() {
        switch self {
        case .off:
            self = .on
        case .on:
            self = .off
        }
    }
}
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle()
// lightSwitch is now equal to .on

이 프로토콜을 따르는 값타입 형에서 toggle()메소드를 변경해 사용할 수 있습니다.

클래스에서 프로토콜 필수 이니셜라이저의 구현 (Class Implementation of Protocol Initializer Requirements)

프로토콜에서 필수로 구현해야하는 이니셜라이저를 지정할 수 있습니다.

protocol SomeProtocol {
    init(someParameter: Int)
}

프로토콜에서 특정 이니셜라이저가 필요하다고 명시했기 때문에 구현에서 해당 이니셜라이저에 required 키워드를 붙여줘야 합니다.

class SomeClass: SomeProtocol {
    required init(someParameter: Int) {
        // initializer implementation goes here
    }
}
NOTE
클래스 타입에서 final로 선언된 것에는 required를 표시하지 않도 됩니다. final로 선언되면 서브클래싱 되지 않기 때문입니다.

특정 프로토콜의 필수 이니셜라이저를 구현하고, 수퍼클래스의 이니셜라이저를 서브클래싱하는 경우 이니셜라이저 앞에 required 키워드와 override 키워드를 적어줍니다.

서브클래싱? → 상속 관계!

override? someSuperClass에 있는 친구를 상속받겠다 할때 override 쓸 수 있음.

super. 을 쓰는 경우와 필요없는 경우?

protocol SomeProtocol {
    init()
}

class SomeSuperClass {
    init() {
        // initializer implementation goes here
    }
}

class SomeSubClass: SomeSuperClass, SomeProtocol {
    // "required" from SomeProtocol conformance; "override" from SomeSuperClass
    required override init() {
        // initializer implementation goes here
    }
}

2. 두 번째 학습 내용: 클래스의 상속 (Inheritance)

상속 (Inheritance)이란? 클래스의 여러 속성을 다른 클래스에 물려 줌

A class can inherit methods, properties, and other characteristics from another class. When one class inherits from another, the inheriting class is known as a subclass, and the class it inherits from is known as its superclass. Inheritance is a fundamental behavior that differentiates classes from other types in Swift.

the inheriting class → a subclass: 상속을 하는 클래스

the class it inherits from → superclass: 상속의 출처? 클래스

Classes in Swift can call and access methods, properties, and subscripts belonging to their superclass and can provide their own overriding versions of those methods, properties, and subscripts to refine or modify their behavior.

  • 클래스는 superclass에 속해있는 methods, properties, and subscripts 들을 부르고 접속할 수 있음
  • 해당 methods, properties, and subscripts들의 overriding 버전을 제공할 수 있다

Classes can also add property observers to inherited properties in order to be notified when the value of a property changes. Property observers can be added to any property, regardless of whether it was originally defined as a stored or computed property.

  • 클래스는 property observers를 상속된 프로퍼티에 add 할 수 있다
  • notified 받음 ← 언제? 프로퍼티의 값이 변할때

Defining a Base Class

a Base Class? 다른 어떤 클래스로부터도 상속받지 않은 클래스를 기반 클래스라 합니다.

Subclassing

부모로부터 성격을 상속받고 자기 자신 고유의 특성도 추가할 수 있습니다.

Subclassing is the act of basing a new class on an existing class. The subclass inherits characteristics from the existing class, which you can then refine. You can also add new characteristics to the subclass.

Overriding

서브클래스에서는 부모클래스에서 상속받은 것을 재정의할 수 있습니다. 이것을 overriding 이라 부르는데, 오버라이딩은 인스턴스 메소드, 타입 메소드, 인스턴스 프로퍼티, 타입 프로퍼티, 서브스크립트 모두에 대해 가능합니다.

A subclass can provide its own custom implementation of an instance method, type method, instance property, type property, or subscript that it would otherwise inherit from a superclass. This is known as overriding.

override 정의가 superclass definition이랑 매칭하는지 체크함으로써 정확한 override를 할 수 있게 해줌

Swift helps to ensure your overrides are correct by checking that the override definition has a matching superclass definition.

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "현재 시간당 \(currentSpeed)마일로 주행하고 있습니다."
    }
    func makeNoise() {
    }
}

let someVehicle = Vehicle()
//print("Vehicle: \(someVehicle.description)")
// print "Vehicle: 현재 시간당 0.0마일로 주행하고 있습니다."

class Bicycle: Vehicle {
    var hasBasket = false
}
// The new Bicycle class automatically gains all of the characteristics of Vehicle
// 새로운 new Bicycle은 자동으로 Vehicle 클래스의 모든 속성들을 얻는다.

// By default, any new Bicycle instance you create will not have a basket. You can set the hasBasket property to true for a particular Bicycle instance.
// 자동으로, 새 Bicycle의 어떤 인스턴스든 디폴트 값으로는 Basket이 없는게 되지만
// 아래와 같이 새로운 인스턴스를 생성할 때 특정 인스턴스에는 Basket이 있는거로 값을 변경해줄 수도 있음

let bicycle = Bicycle()
bicycle.hasBasket = true

// 상속받은 프로퍼티 값을 아래와 같이 변경해줄 수 있음
bicycle.currentSpeed = 15.0
//print("Bicycle: \(bicycle.description)")
// print "Bicycle: 현재 시간당 15.0마일로 주행하고 있습니다."

// 상속을 이어서 받은 케이스
// TwoRidersBicycle은 -> Bicycle을 상속받음
// Bicycle은 -> Vehicle을 상속받음
class TwoRidersBicycle: Bicycle {
    var currentNumberOfPassengers = 0
    // Overriding Methods
    override func makeNoise() {
         print("따릉이가 나갑니다 따르르르릉~")
    }
}

let twoRidersBicycle = TwoRidersBicycle()
twoRidersBicycle.hasBasket = true
twoRidersBicycle.currentNumberOfPassengers = 2
twoRidersBicycle.currentSpeed = 22.0

//print("\(twoRidersBicycle.currentNumberOfPassengers)인용 자전거: \(twoRidersBicycle.description)")
// print "2인용 자전거: 현재 시간당 22.0마일로 주행하고 있습니다."

let seoulBicycle = TwoRidersBicycle()
seoulBicycle.makeNoise()
// print "따릉이가 나갑니다 따르르르릉~"

부모클래스의 메소드, 프로퍼티, 서브스크립트의 접근 (Accessing Superclass Methods, Properties, and Subscripts)

super.someMethod, super.someProperty, super[someIndex]
// you access the superclass version of a method, property, or subscript by using the super prefix:

자료 출처:

profile
iOS Developer

0개의 댓글