FC 8장 - Class

Challenger·2021년 9월 15일
0
post-custom-banner

Struct와 Class는 이런 차이점이 있다
코드 상에서는 어떻게 다른지 알아보자

Struct는 Copy해서 할당하기 때문에 personStruct1과 2가 값이 다를 수 있다

Struct

personStruct2에 값을 할당해도 personStruct1의 값은 변하지 않는다

Class

personClass2 = personClass1을 통해 2에 1을 할당한 모습
personClass2 값에 변화를 주었더니 personClass1의 값도 변했다

다시 personClass2 = PersonClass(firstName: "Bob", lastName: "Lee")를 할당했는데
그 아래에 보면
personClass1의 값은 그대로지만 2의 값은 변한 것을 볼 수 있다

그러나 맨 아래에서 personClass1에 personClass2를 할당했더니
다시 Bob으로 다 일치된 것을 확인할 수 있다

Struct VS Class 언제, 무엇을 써야 할까?

Struct는 이럴 때 쓰자!

  1. 두 object를 "같다, 다르다"로 비교해야 하는 경우
  1. Copy된 각 개체들이 독립적인 상태를 가져야 하는 경우

  2. 코드에서 오브젝트의 데이터를 여러 스레드에 걸쳐 사용할 경우

Class는 이럴 때 쓰자!

  1. 두 object의 인스턴스 자체가 같음을 확인해야 할 때

  2. 하나의 객체가 필요하고, 여러 대상에 의해 접근되고 변경이 필요한 경우

아 그래도 모르겠다면!

  1. 일단 Sturct로 쓰자 (Struct에서 Class로 바꾸는 건 쉽다) Swift는 Struct를 좋아한다

Class 상속

Class가 비슷하고 A가 B에 포함될 경우
A를 B에 상속시키고 B에는 A와 겹치지 않는 부분만 적을 수 있다


위의 예시처럼 Person(기본 틀)은 Super Class, Student는 SubClass다


이러한 상속 규칙을 수립할 수 있다
3번 상속의 깊이는 상관이 없다는 것은 서브 클래스를 부모클래스로한 서브클래스가 생길 수 있다는 뜻

여기서 잠꽌!!!!!!

is란 무엇인가

var yangwon = Person(name: "Chall")

if yangwon is Person {
    print(true)		// true
}    

이렇게 is를 쓰면 yangwon의 Super Class가 Person이 맞나 아닌가 판단할 수 있다
맞으면 true, 틀리면 false

let char: Character = "A"
 
char is Character       // true
char is String          // false
 
 
let bool: Bool = true
 
bool is Bool            // true
bool is Character       // false

이렇게 class가 아닌 곳에서도 활용 가능

as?

가장 하단을 보면 된다
if let movie = item as? Movie
이걸 해석하면 item이 Movie를 상속받았어?
만약 그렇다면 movie에 값이 들어갈 수 있어서 if가 참이 된다
따라서 print를 실행해!
이런 의미이다

만약 item이 Movie를 상속받지 않았다면 nil이기 때문에 movie에 할당할 수 없고
따라서 else if로 넘어가게 된다

즉 as?는 "그게 이걸 상속받았니 안 받았니?" 이렇게 물어본다고 이해하면 된다

as(upcasting)


와 이것 때문에 정신 나가는 줄
아니 athlete1 = athelete2 as StudentAthlete
이게 의미하는 건 athelete2가 FootballPlayer지만 Student인척 해달라는 의미인데
Student임에도 불구하고 train()을 했을 때 +2씩 증가하더라 (FootballPlayer의 프로퍼티를 받았다는 의미)

알고보니까 이게 싹다 Student처리되는 게 아니라 override된 것은 자식으로 처리하는 것이었음

상속은 언제 하면 좋을까?

상속의 장점은 중복되는 코드를 제거할 수 있음
단 깊어지면 복잡해져서 유지보수가 어려워진다
고로 짬에서 나오는 바이브가 필요한...

1. Single Responsibility(단일 책임)

  • 클래스는 한 개의 고려사항만 가지면 된다 한 가지 일에 집중할 수 있도록 정체성도 모호해지고 유지보수도 하기 어렵기 때문에 단일 책임을 고려하면 좋다

2. Type Safety 타입이 분명해야 할 때

3. Shared Base Classes(다자녀가 있다!)

내용 자체가 다르게 구현되어야 할 때
ex. 학생의 학습이라 치면 음악, 체육, 문학 등 다르니까 이럴 때는 상속을 이용하면 좋다)

4. Extensibility

확장성이 필요한 경우 - 캔이라는 클래스를 만들어서 콜라캔, 맥주캔 이렇게 확장할 경우

5. Identity

정체를 파악하기 위해 변수가 있는데 학생인데 체대생? 미대생? 이런 것을 확인해야 할 때

init 생성

2-phase Initialization (클래스 생성 시 2단계)

Phase 1

  • 모든 스토어드 프로퍼티는 모두 init 처리되어야 한다
  • 자식프로퍼티부터 init하고 뒤에 super로 부모클래스 프로퍼티를 init 처리한다

Phase 2

  • Phase 1이 마무리되기 전에는 사용할 수 없음 그래서 Phase 2가 있다.
  • Phase 2는 반대 방향 프로퍼티를 다 세팅하고 매서드를 쓸 수 있다

designated init(주 이니셜라이져) VS convenience init(간편하게 쓰는 이니셜라이져)


(강사님의 잘린 머리...)


그림으로 보면 이러하다


코드상에서는 이렇게 convenience를 활용할 수 있다
근데 override로 init을 가져와서 활용하는 건 아직 모르겠다
일단 넘기고 싶은 욕구가 솟아오르기 때문에 일단 패스

요약

  • 클래스 안에는 여러 init을 만들 수 있다.
  • 이게 크게 주, 부 init으로 나누어 볼 수 있다.
  • 부 init은 다른 init을 호출하게 되어있다.
  • 최종적으로 부 init은 주 init 불러야 한다
profile
롤 챌린저의 100일 개발 도전기
post-custom-banner

0개의 댓글