6주차는 클래스 / failable/ initialize 등 알아보도록 하겠습니다.
[클래스]
클래스는 객체 혹은 인스턴스라고 부릅니다. c++, 자바 등 여러가지 언어에서 클래스를 사용할 수 있습니다.
스위프트 언어에서는 변수를 선언하고 초기화 할 수 있는 필드를 프로퍼티라고 부릅니다.
자바/ c# 등 다른 언어에서는 필드라고 부르지만 스위프트에서는 프로퍼티라고 부르니 혼동이 없기를 바랍니다.
그리고 함수를 Method라고 부르는 것을 알고 있으면 좋을것 같습니다.
스위프트에서는 클래스를 사용하기 위해서 클래스의 기본 구조로는 해당 사진처럼 프로퍼티(변수)/ 인스턴스 메서드(함수)등 정의해야하는 구조를 가지고 있습니다.
//Class 기본 구조
class Man{
var age : Int = 1
var weight : Double = 1.1
}
스위프트에서 클래스는 Stored Propery(변수)를 정의하기 위해서는 반드시! 초기값을 넣어줘야 합니다.
초기값을 넣지 않게되면 오류가 나오는 것을 알 수 있습니다.
하지만 변수에 옵셔널을 넣게 되면 어떻게 될까?
class Man{
var age : Int! //= 1
var weight : Double? //= 1.1
}
해당 코드처럼 초기값을 업애고 옵셔녈 변수로 정의해서 출력하게되면 값이 비어있다 즉, nil의 값이 출력이 되는것을 알 수 있습니다.
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)
해당 소스에서 클래스에서 정의를 하고 클래스를 호출하는 예입니다.
클래스 인스턴스 초기화 ( init())
인스턴스가 만들어지게되면 자동적으로 이니셜라이션이 호출이 됩니다.
class Man{
var age : Int = 1
var weight : Double = 3.5
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(yourAge: Int, yourWeight : Double){
age = yourAge
weight = yourWeight
} //designated initializer
}
//var kim : Man = Man() //오류
//init()을 하나라도 직접 만들면 default
var kim : Man = Man(yourAge:10, yourWeight:20.5)
kim.display()
init를 사용해 매개변수를 받는 값이 있으면 반드시 클래스 메서드를 호출할 때 인자값을 넣어야 한다.
* 프로퍼티를 초기화 하는 것을 designated initializer라고 부른다.(알고있어야됨.)*
self -> 현재 메서드나 클래스에 프로퍼티를 가리킬 때 self를 사용합니다.
자바나 c언어 등 다양한 언어에서는 this를 사용하지만 스위프트에서는 self를 사용하는것을 알아야합니다.
(self 중요함.)
method Overloading(생성자 중첩)
매개변수의 개수와 자료형이 다른 같은 이름의 함수를 여러 개 정의(재정의)를 말합니다.
class Man{
var age : Int = 1
var weight : Double = 3.5
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){ //1
self.age = age
self.weight = weight
}
init(age: Int){ //2
self.age = age
}
}
var kim : Man = Man(age:10, weight:20.5) //1
var kim1 : Man = Man(age:10) //2
//var kim2 : Man = Man()
//init가 없다면 인스턴스 만드는 방법
kim.display()
kim1.display()
해당 이니셜라이즈를 통해서 클래스 메서드를 호출하는데 kim은 매개변수 두 개/ kim1은 매개 변수 1개의 값을 받는데
이니셜라이즈 정의할 때 매개변수 2개를 받는 클래스메서드 와 1개만 받는 클래스 메서드를 정의 해둔것을 알 수 있습니다. 이것을 바로
method overloading(재정의)라고 부릅니다. 그리고 자료형도 여러개 일 경우에 메서드 오버로딩에 포함됩니다.
해당 사진은 uiimage 에 관련된 내용에 이니셜라이져가 얼마나 많이 사용하는지에 대해서 알 수 있는 내용입니다.
그만큼 이니셜라이저가 중요하다는것을 알 수 있습니다.
[클래스(class) 상속]
객체지향에서 많이 사용하는 내용인 상속 내용입니다. 부모 클래스를 수퍼 클래스 / 자식 클래스를 서브 클래스라고 부릅니다.
스위프트 / c# 등 상속을 할 때 ( : )를 사용합니다.
상속을 받을 때 콜론 ( : ) 뒤에 부모 클래스, 부모클래스는 딱 하나만 가능하고 부모클래스 외에 상속을 하는 경우에는 프로토콜 명을 사용해 상속을 받는다.
맨에 대해서 상속을 받고 있는 student이다. 하지만, 부모와 자식에 같은 메서드가 있으면 자식을 우선적으로 호출하는 것이 오버라이드(over ride)라고 부른다.
해당 소스를 고치는 경우 다음과 같다.
// 부모 클래스 Man 정의
class Man {
// 나이와 몸무게를 저장할 속성 정의
var age: Int
var weight: Double
// 객체의 나이와 몸무게를 출력하는 메서드
func display() {
print("나이=\(age), 몸무게=\(weight)")
}
// 생성자: 객체를 초기화할 때 age와 weight를 설정하는 역할
init(age: Int, weight: Double) {
self.age = age // 매개변수로 받은 age 값을 속성 age에 할당
self.weight = weight // 매개변수로 받은 weight 값을 속성 weight에 할당
}
}
// Student 클래스는 Man 클래스를 상속받음
class Student: Man {
// 새로운 속성 name 추가
var name: String
// display 메서드를 오버라이드하여 name도 출력하도록 변경
override func display() {
print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
}
// 생성자: Student 객체를 초기화할 때 age, weight, name을 설정
init(age: Int, weight: Double, name: String) {
self.name = name // Student 클래스의 새로운 속성 name에 값 할당
// 부모 클래스 Man의 생성자를 호출하여 나이와 몸무게를 설정
super.init(age: age, weight: weight)
// 만약 super.init()을 호출하지 않으면 에러 발생:
// 'super.init' isn't called on all paths before returning from initializer
// 즉, 부모 클래스의 속성을 초기화하지 않았기 때문에 발생하는 에러
}
}
// Student 클래스의 인스턴스를 생성하고 초기화
var lee: Student = Student(age: 20, weight: 65.2, name: "홍길동")
// Student 클래스의 display 메서드를 호출하여 이름, 나이, 몸무게 출력
lee.display()
[failable initializers] - 실패 가능한 생성자.
항상 failable initializers를 정의할 때 무조건 init?을 사용해야한다.
해당 사진들을 보면 init?가 많은것을 알 수 있다 그만큼 중요하다는 것이고 모바일 개발을 할 때 모르면 안되는 중요한 문법이기도 하다.
오류 상황에서 nil을 리턴하는 조건문이 존재합니다.
ex) return nil
해당 사진에서보면 옵셔널 타입이 존재하지않아 오류가 생기는 것을 알 수 있다.
그렇다면 해결방법은 무엇이 있을까?
아래에 두 가지방법으로 해결을 할 수 있다.
1. 리턴 값이 nil이 나올 수 있기 때문에 ??를 추가해 오류를 해결하는 방법
2. 똑같은 경우로 !를 추가해 오류를 해결하는 방법 등 두 가지에 방법이 존재한다.
failable initialize가 있는 클래스의 인스턴스 생성
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()
하지만 3과 4의 방법을 통해서 강제로 언래핑 하게 되면 crash 현상이 일어난다.
// 부모 클래스 Man 정의
class Man {
var age: Int // 나이를 저장할 속성
var weight: Double // 몸무게를 저장할 속성
// 객체의 나이와 몸무게를 출력하는 메서드
func display() {
print("나이=\(age), 몸무게=\(weight)")
}
// 실패 가능한 생성자(failable initializer)
init?(age: Int, weight: Double) {
// 나이 또는 몸무게가 0 이하일 경우 초기화를 실패하고 nil을 반환
if age <= 0 || weight <= 0.0 {
return nil
}
else {
// 유효한 값이면 속성에 값을 할당
self.age = age
self.weight = weight
}
}
}
// Man 클래스의 인스턴스 kim 생성
// age = 1, weight = 20.5로 초기화가 유효하므로 객체가 성공적으로 생성됨
var kim: Man = Man(age: 1, weight: 20.5)!
// kim 인스턴스의 display 메서드를 호출하여 나이와 몸무게 출력
kim.display()
// if-let 구문을 사용하여 lee 인스턴스 생성 시 안전하게 처리
// age = 1, weight = 0.0으로 인해 초기화가 실패하여 lee는 nil이 됨
if let lee = Man(age: 1, weight: 0.0) {
// 만약 lee가 nil이 아니라면(초기화 성공), display 메서드를 호출하여 출력
lee.display()
}
// 초기화가 실패하여 else 블록이 실행되지 않음
정리한 내용을 위에 소스코드와 주석을 통해서 정리가 되어있다.
'iOS 프로그래밍 기초' 카테고리의 다른 글
[iOS 프로그래밍 기초] 9주차 (3) | 2024.10.31 |
---|---|
[iOS프로그래밍 기초] 7주차 (3) | 2024.10.17 |
[iOS 프로그래밍] 6주차 일급 객체(일급 시민)와 클로저 기초 (1) | 2024.10.09 |
[iOS 프로그래밍 기초] 4주차 (1) | 2024.09.26 |
[iOS 프로그래밍] 3주차 (0) | 2024.09.19 |