갓생 살기 3회차 .. 오늘은 약간 김이 빠지는 하루였지만..! 아 오늘도 화이텡 ~~!~!~!!!~!~!!~!~! 🤓
실패 가능 생성자는
로 간단하게 얘기할 수 있죠잉?
코드를 보면서 얘기해볼까요?
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty {
return nil // species 가 nil일 수도 있으니! 옵셔널 작업을 함.. nil 이면 nil을 리턴 하도록!
}
self.species = species
}
}
let a = Animal(species: "Giraffe") // ====> 인스턴스 생성
let b = Animal(species: "") // 문자열이기에 유효한 타입이지만 =====> nil
species 가 nil
일 수도 있응께.... 난 ?
를 붙여서.. 실패 가능 생성자를 만든 것 뿐..
어떻게 만드는지 알겠죠?
아니 근데 실패 가능 생성자는 enum
에서도 구현 가능한 거.. 혹시 아나?
enum TemperatureUnit {
case kelvin
case celsius
case fahrenheit
init?(symbol: Character) {
switch symbol {
case "K":
self = TemperatureUnit.kelvin
case "C":
self = TemperatureUnit.celsius
case "F":
self = TemperatureUnit.fahrenheit
default:
return nil
}
}
}
let c: TemperatureUnit = TemperatureUnit.celsius // TemperatureUnit()
let f: TemperatureUnit? = TemperatureUnit(symbol: "F")
일반 적인 enum
은 위와 같은 식으로 init
뒤에 ?
를 붙여서 실패 가능 생성자로 표현해야하지만,
// 열거형의 원시값 설정 (실패가능 생성자의 구현과 유사)
enum TemperatureUnit1: Character {
case kelvin = "K"
case celsius = "C"
case fahrenheit = "F"
}
// 원시값이있는 열거형은 자동으로 실패가능 생성자 init?(rawValue :)를 구현함 ==> 일치하면 인스턴스 생성, 아니면 nil
let f1: TemperatureUnit1? = TemperatureUnit1(rawValue: "F") // .fahrenheit
let u: TemperatureUnit1? = TemperatureUnit1(rawValue: "X") // nil
원시값을 가진 enum
은! 자동으로.. 실패가능 생성자를 만드는 사실.. 알고 있었나?
여튼 그랬다는 사실 ~
소멸자는!
이렇게 간단 요약을 해봤음 .. 클래스에서만 존재하며 간단한 코드를 보여주겠음
class Aclass {
var x = 0
var y = 0
deinit {
print("인스턴스의 소멸 시점")
}
}
var a: Aclass? = Aclass()
a = nil // 메모리에 있던 a인스턴스가 제거됨
아직 이해가 잘 가지 않아, 주말에 좀 더 공부 할 예정이다 !
다음은 타입캐스팅!
타입캐스팅으로는 is 연산자, as 연산자가 있지만..!
일단 간단하게 상속을 다시 되집어 볼거임!
class Person {
var id = 0
var name = "이름"
var email = "abc@gmail.com"
}
class Student: Person {
// id
// name
// email
var studentId = 1
}
class Undergraduate: Student {
// id
// name
// email
// studentId
var major = "전공"
}
let person1 = Person()
person1.id
person1.name
person1.email
let student1 = Student()
student1.id
student1.name
student1.email
student1.studentId // 추가적으로
let undergraduate1 = Undergraduate()
undergraduate1.id
undergraduate1.name
undergraduate1.email
undergraduate1.studentId
undergraduate1.major // 추가적으로
기본적으로 상속이 어떻게 진행이 되는지는 100% 이해가 됐음.. 웬일이지
위 코드에서 만든 인스턴스들을 이제 이용할거임! 왜? 인스턴스 타입을 검사하는is
연산자 때문!
is
연산자는: 타입에 대한 검사를 수행하는 연산자임
참이면 true 를 리턴하고,, 거짓이면 false 를 리턴하고.. 아마 상속관계의 계층에서 포함관계를 생각해보면 좀 쉬움!!
person1 is Person // true
person1 is Student // false
person1 is Undergraduate // false
// 학생 인스턴스는 대학생 타입은 아니다. (사람/학생 타입니다.)
student1 is Person // true
student1 is Student // true
student1 is Undergraduate // false
// 대학생 인스턴스는 사람이거나, 학생이거나, 대학생 타입 모두에 해당한다.
undergraduate1 is Person // true
undergraduate1 is Student // true
undergraduate1 is Undergraduate // true
요렇게 표현 할 수 있겠죠?
is
를 알아봤으니 이제 as
를 알아보죠 ~
가볍게 as!
, as?
와 as
이렇게 2개로 나눌 수가 있음..
자세히 고고!
타입캐스팅 / 타입캐스팅 연산자 (이항 연산자)
(1) Upcasting (업캐스팅)
(2) Downcasting (다운캐스팅) (실패가능성이 있음)
let ppp = person as? Undergraduate
위와 같은 코드를 해석하자면.. person
이라는 변수에 들어있는 인스턴스를 as?
를 이용해 Undergraduate
로 변환을 하고ppp
에 넣는다!
라고 해석하면 될 것 같아요..
아무래도 ?, !
를 사용하다보니, 옵셔널이 있으므로..
if let newPerson = person as? Undergraduate { // if let 바인딩과 함께 사용 (옵셔널 언래핑)
newPerson.major
print(newPerson.major)
}
로 주로 사용이 됩니다!
as!
가 사용될 땐
let person3: Undergraduate = person as! Undergraduate
person3.major
강제 언래핑을 한다고 생각하니, if let
같은 식을 사용하지 않겠죠?
as?
, as!
는 다운캐스팅을 진행한 것이고..! as
는 업캐스팅을 한건데..!
이제 요놈을 알아볼거에요
let undergraduate2: Undergraduate = Undergraduate()
undergraduate2.id
undergraduate2.name
undergraduate2.studentId
undergraduate2.major
//undergraduate2.name = "길동"
let person4 = undergraduate2 as Person // 항상 성공 (컴파일러가 항상 성공할 수 밖에 없다는 것을 알고 있음)
person4.id
person4.name
딱 봐도 하위클래스의 메모리구조로 저장된 인스턴스를 상위클래스 타입으로 인식해오는 걸 알 수 있습니다!
1) Any 타입
var some: Any = "Swift"
some = 10
some = 3.2
(some as! String).count
타입이 이것저것 섞였을 때 주로 이용하는 걸 알 수 있죠..
2) AnyObject 타입
let array: [Any] = [5, "안녕", 3.5, Person(), Superman(), {(name: String) in return name}]
//array[1].count
(array[1] as! String).count
TIL 시리즈는 막연히 제가 배운 걸 기록하는 공간입니다.