TypeCasting의 목적

Heedon Ham·2023년 7월 31일
0

iOS 이것 저것

목록 보기
6/17
post-thumbnail

Weekly Sesac: Any와 TypeCasting

지난번에도 한번 작성한 내용이지만 왜 type casting이 필요할까에 대해 다뤄보려 한다.

Type Casting
Determine a value’s runtime type and give it more specific type information.

Type casting is a way to check the type of an instance, or to treat that instance as a different superclass or subclass from somewhere else in its own class hierarchy.

instance의 type을 체크하거나, 혹은 생성된 타입과 다른 클래스인것처럼 다루는 것을 의미한다.

SuperClass와 SubClass instance 관계는 다음과 같다.

superClassSubClassInstances

SubClass의 instance는 SuperClass type으로도 활용이 가능하다. SubClass는 SuperClass의 특성을 상속받았기 때문.

반면 SuperClass의 instance는 SubClass type으로 인식하지 않는다. SuperClass에는 SubClass의 property들이 다 존재하지 않기 때문.

이는 마치 집합 개념과 유사하다.
UIKit의 상속 관계를 집합처럼 나타내면 다음과 같이 나타낼 수 있다.

uikitInheritance

이를 SuperClass와 SubClass 맥락으로 본다면 다음처럼 표현할 수 있다.

let backView = UIView()
let pushButton = UIButton()
  • UIView의 instance인 backView는 UIView의 property를 모두 가지고 있다.
  • UIButton의 instance인 pushButton은 UIButton의 property를 모두 가지고 있다.
  • UIButtonUIViewUIControl class를 상속받으므로 UIControl의 property와 UIView의 property를 모두 가지고 있다.

따라서 backView instance를 UIButton type으로 downcasting해 활용하는 것은 불가능하다. 애초에 backView instance는 UIButton의 property를 가지고 있지 않기 때문이다.

하지만 pushButton은 UIView의 property를 모두 가지고 있으므로, UIView type이라고 인식해도 무방하다.

굳이 누가 그렇게 상위 class로 인식해서 씀?

개발자 자신은 그렇게 쓰기 싫겠지만 함수 메서드를 활용하다보면 일반적인 타입으로 return하기 위해 상위 class로 인식되는 경우가 존재한다.

Cell 구현

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
	let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ExampleCollectionViewCell", for: indexPath) as! ExampleCollectionViewCell
    
    // Configure the cell
    let data = dataList[indexPath.row]
        
    cell.configCell(data: data)
        
    return cell
}

as 없이 재사용 cell을 정의하면 type이 UICollectionViewCell이다.

이 상태로 cell을 return해도 컴파일 에러는 나타나지 않는다.

하지만 ExampleCollectionViewCell type의 method와 property에 접근하기 위해선 UICollectionViewCell을 상속받은 ExampleCollectionViewCell로 downcasting 해야 한다.

downcasting 없이 configCell method에 접근하면 존재하지 않는 요소라고 컴파일 에러를 일으킨다.

ViewController instance 구현

UICollectionView에서 해당 cell을 눌렀을 때, DetailViewController로 화면 전환되는 코드이다.

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
	let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let detailVC = storyboard.instantiateViewController(withIdentifier: DetailViewController.identifier)
        
    detailVC.title = dataList[indexPath.row].title
        
    navigationController?.pushViewController(detailVC, animated: true)
}

이 코드에서는 cell에서 화면 전환 시, 해당 ViewController의 NavigationBar의 title 설정만 존재하고, 데이터를 넘겨주지 않기 때문에 detailVC가 downcasting없이 UIViewController로 활용되어도 컴파일 에러가 나타나지 않는다.

하지만 만약 detailVC의 label이나 imageView에 관련 정보를 넘겨주기 위해 접근하는 코드가 있었다면 컴파일 에러가 발생했을 것이다.

type casting 그래서 꼭 필요하긴 한가?

type casting 그 자체로는 큰 문제가 없다. 해당 class의 instance의 property에 접근 권한이 있어야하기 때문에 상속받는 downcasting이 필요한 것이다.

이는 class가 메모리에 올라오는 구조와도 연관이 있는데 이는 메모리를 본격적으로 다룰 때 다시 정리하기로 하고 간단하게 정리하면 다음과 같다.

  • SubClass는 SuperClass의 property를 모두 포함해서 메모리에 올라오는 것이 아니다.
  • 상속받은 SuperClass의 property들은 SuperClass의 주소값으로 가리킨다. (Reference)
  • 따라서 SubClass의 instance는 SubClass를 가리키고, 그 SubClass가 SuperClass를 가리키기에 instance는 SuperClass로 접근이 가능하다.
  • 하지만 SuperClass의 instance는 SubClass의 주소를 모르기에 SubClass의 property에 접근이 불가능하다.
profile
dev( iOS, React)

0개의 댓글