이번주에 보고 넘어갈것들
- 클래스
- failable
- 상속 (클래스)
- initialize ( init )
- self
1-1. 객체 vs 클래스 vs 인스턴스
1-2. 객체지향 용어 비교하기
1-3. Structures and Classes (구조체와 클래스)
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures/
1-4. 객체 인스턴스
https://en.wikipedia.org/wiki/Instance_(computer_science)
인스턴스는 모든 물체의 구체적인 발생을 의미하며(실체 존재), 일반적으로 컴퓨터 프로그램 실행 중에 존재합니다.
공식적으로 "인스턴스"는 다음과 같은 동의어입니다
"객체"는 각각 특정 값(실현)이며, 이를 인스턴스 객체라고 할 수 있습니다.
"instance(인스턴스)"는 개체의 고유한 정체성을 강조합니다.
1-5. 클래스 vs 인스턴스
1-6. swift 클래스 선언하는 방법
2-1. 프로퍼티란?
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties/
속성(프로퍼티)은 값을 특정 클래스, 구조 또는 열거와 연관시킵니다.
저장된 속성은 인스턴스의 일부로 상수 및 변수 값을 저장하는 반면, 계산된 속성은 값을 계산합니다(저장 안함).
계산된 속성은 클래스, 구조 및 열거에 의해 제공되고, 저장된 속성은 클래스 및 구조에 의해서만 제공됩니다.
2-2. 프로퍼티 = 클래스 내부에 선언되는 상수및 변수등을 의미함
프로퍼티는 3가지 방법을 하나라도 이용해야 사용이 가능합니다.
1. 초기값이 있거나
2. init을 이용해서 초기화하거나
3. 옵셔널 변수(상수)로 선언(자동으로 nil로 초기화)
2-3. 초기값을 부여하거나, 옵셔널 변수를 이용한 선언
2-4. 메서드 (method)
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/methods/
2-5. 메서드 정의
2-6. 인스턴스 만들고 접근하기
class Man{
var age : Int = 1
var weight : Double = 3.5
func display(){ // << 인스턴스 메서드
print("나이=\(age), 몸무게=\(weight)")
}
}
var kim : Man = Man()
kim.display() //인스턴스 메서드는 인스턴스가 호출
print(kim.age)
2-7. 클래스 메서드
class Man{
var age : Int = 1
var weight : Double = 3.5
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
class func cM(){
print("cM은 클래스 메서드입니다.")
}
static func scM(){
print("scM은 클래스 메서드(static)")
}
}
var kim : Man = Man()
kim.display() //인스턴스 메서드는 인스턴스가 호출
Man.cM() //클래스 메서드는 클래스가 호출
Man.scM() //클래스 메서드는 클래스가 호출
3-1. init에 대해서
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization/
3-2. init을 이용한 인스턴스 초기화
init은 클래스나 구조체, 열거형 인스턴스가 생성될때 (실행할때) 수행하는 초기화를 의미합니다.
인스턴스가 만들어지면서 자동으로 호출되는 특징도 가지고 있습니다.
주의 : init을 하나라도 만들었다면, 디폴트 이니셜라이저(default initializer)는 자동으로 사라짐
코드를 보면 이해가 되실껍니다.
class Man{
var age : Int = 1 // << 얘네가 이니셜라이저
var weight : Double = 3.5 // << 얘네가 이니셜라이저
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(yourAge: Int, yourWeight : Double){ // init을 만들어서 위의 디폴트 이니셜라이저는 자동으로 무시
age = yourAge
weight = yourWeight
} //designated initializer
}
//var kim : Man = Man() //오류
var kim : Man = Man(yourAge:10, yourWeight:20.5)
kim.display() // 10 , 20.5
"그러면 디폴트 이니셜라이저 필요없는데 지워도 되는거 아닌가요? 라고 생각하실수 있습니다."
= 말하자면 가능합니다 (잘못말한거 아니에요, 실행도 해봤습니다)
4-1. self
self는 클래스 내에 존재하는 변수를 직접 지정하거나 매개변수와 구분하기 위해 사용합니다.
예시를 들어서 age = age는 바로 오류가 나버리지만,
self.age라고 한다면 클래스 내에 존재하는 age를 지칭하지 않는 별개의 변수로 본다는 의미가 됩니다.
(자료형에 따로 이름을 붙이지않고, 공통된 이름을 사용할때 충돌을 막기위한 해결책)
4-2. 메서드 오버라이딩 (생성자 중첩)
https://en.wikipedia.org/wiki/Function_overloading
매개 변수의 개수와 자료형이 다른 이름의 함수를 여럿 정의하는걸 생성자 중첩이라고 합니다.
이러한 방법을 이용해서 두가지 방법으로 인스턴스를 만드는것도 가능합니다.
5-1. UIImage클래스의 init() 오버라이딩
5-2. 실패 가능한 생성자 ( failable initializers [init?] )
5-3. 실패 가능한 생성자 : init? , init!
쉽게 풀어쓰자면, init에 ? 나 !를 붙여서 상황에 따라서 실패하게 만드는 일종의 트리거 역할을 합니다.
(조건에 따라서 어떤때는 될수도 있고, 안되서 막히는 경우도 존재)
이렇게 써도 이해가 안되실텐데 밑에 나오는 코드를 보시면 이해가 되실껍니다.
5-4. 실패 가능한 생성자가 있는 클래스 인스턴스
class Man{
var age : Int
var weight : Double
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init?(age: Int, weight : Double){
if age <= 0 {
return nil
}
else {
self.age = age
}
self.weight = weight
} // failable initializer
}
var kim : Man = Man(age:10, weight:20.5) //옵셔널을 안풀어서 에러가 심판하러 옴...
kim.display()
var lee : Man = Man(age:0, weight:3.5) //error
lee.display()
//error 를 주목해봅시다.
우리나라 기준이지만, 태어날때 1살로 정의합니다.
하지만 0살인 사람이 존재할수 있을까요? (만 나이 기준이면 몰라도 기본적으로 존재할수가 없잖아요?)
그러기에 실행할수 없는, 즉 실패할수 밖에 없으므로 이줄은 강제로 생략되어 출력되지 않습니다.
그러다보니, Xcode나 컴파일러등 이 코드를 돌리려고 하면, 아주 난리가 납니다. (에러가 빗발침)
그러다보니 안전하게 사용하기 위해선 아래의 방법을 이용해야 합니다.
5-5. 실패 가능한 생성자가 있는 클래스 인스턴스 생성
class Man{
var age : Int
var weight : Double
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init?(age: Int, weight : Double){
if age <= 0 {
return nil
}
else {
self.age = age
}
self.weight = weight
}
}
var kim : Man? = Man(age:1, weight:3.5)
//1-1.옵셔널 형으로 선언
if let kim1 = kim { //1-2.옵셔널 바인딩
kim1.display()
}
//2.인스턴스 생성과 동시에 옵셔널 바인딩
if let kim2 = Man(age:2, weight:5.5) {
kim2.display()
}
//3.인스턴스 생성하면서 바로 강제 언래핑
var kim3 : Man = Man(age:3, weight:7.5)!
kim3.display()
//4.옵셔널 인스턴스를 사용시 강제 언래핑
var kim4 : Man? = Man(age:4, weight:10.5)
kim4!.display()
5-5. 실패 가능한 생성자가 nil 반환 (강제 언래핑)
주의 : 강제 언래핑은 자칫 크래쉬가 나거나, 심하면 블루스크린이 뜰수도 있음.
class Man{
var age : Int
var weight : Double
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init?(age: Int, weight : Double){
if age <= 0 {
return nil
}
else {
self.age = age
}
self.weight = weight
}
}
var kim : Man? = Man(age:-1, weight:3.5)
//옵셔널 형으로 선언
if let kim1 = kim { //옵셔널 바인딩
kim1.display()
}
if let kim2 = Man(age:0, weight:5.5) {
kim2.display()
}
var kim3 : Man = Man(age:0, weight:7.5)!
kim3.display()
5-5-2. 위코드에서 몸무게 검사까지 추가한 코드
class Man {
var age: Int
var weight: Double
func display() {
print("나이=\(age), 몸무게=\(weight)")
}
init?(age: Int, weight: Double) {
if age <= 0 || weight <= 0.0 {
return nil
} else {
self.age = age
self.weight = weight
}
}
}
var kim : Man? = Man(age:-1, weight:3.5) // error!! 크래쉬 위험
if let kim1 = kim { //옵셔널 바인딩
kim1.display()
}
if let kim2 = Man(age:1, weight:5.5) {
kim2.display()
}
var kim3 : Man = Man(age:0, weight:7.5)! // error!! 크래쉬 위험
kim3.display()
6-1. inheritance (상속)
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/inheritance/
6-2. 부모 클래스와 자식 클래스
주의 : 부모 클래스를 영어로 읽을때 슈퍼 클래스라고 읽으면 안됩니다, 수퍼 클래스가 맞는말입니다. (발음 주의)
6-3. swift에서의 상속법
6-4. 부모 클래스가 가진것을 물려받아 사용하기
class Man{
var age : Int = 1 //여기서 부터
var weight : Double = 3.5
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age
self.weight = weight //여기까지 자동으로 넘어감
}
}
class Student : Man { }
//비어있지만 Man의 모든 것을 가지고 있음
var kim : Man = Man(age:10, weight:20.5)
kim.display()
var lee : Student = Student(age:20,weight:65.2)
lee.display()
print(lee.age)
6-5. 부모 클래스가 가진것을 물려받고, 더추가해서 사용하기
class Man{
var age : Int
var weight : Double
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age
self.weight = weight
}
}
class Student : Man {
var name : String
func displayS() {
print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double, name : String){
self.name = name
super.init(age:age, weight:weight) //이 줄을 안쓰면?
}//error:'super.init' isn't called on all paths before returning from initializer
}
var lee : Student = Student(age:20,weight:65.2,name:"홍길동")
lee.displayS()
lee.display()
주석이 된 부분을 안쓰면 바로 오류로 직행합니다.
에러를 해석하면 이니셜라이저에서 돌아가기전에 super.init을 호출할수가 없어서 오류가 나다고 합니다.
정확하게 말하면 값을 받았는데 부모클래스를 사용할수가 없어서 오류가 난다. 라고 보면될것 같습니다
자식 클래스에 선언한 init은 자료형만 선언 되었을뿐,
위에서 지정하는것을 따라야하기 때문에, 단독 지정으로는 오류가 납니다.
(좀더 자세히 말하자면 단독적으로 자식 클래스가 부모클래스 자료들을 사용하려해서 오류가 나는것)
6-6. override : 같은 메서드가 있다면 자식 클래스가 우선
'iOS' 카테고리의 다른 글
iOS프로그래밍 9주 [앱 개선 , 여러가지 버튼] (1) | 2024.11.04 |
---|---|
iOS 프로그래밍 기초 (7주) [ Xcode를 이용한 앱 설계 , 개발 ] (1) | 2024.10.20 |
iOS 프로그래밍 기초 (5주) [ first class object , citizen , 클로저] (0) | 2024.10.05 |
iOS 프로그래밍 기초 (4주) [함수,메소드(method)] (7) | 2024.09.29 |
iOS 프로그래밍 기초 (3주) [optional,as,nil,연산자,제어문] (1) | 2024.09.20 |
댓글