-
[6주차] Swift 문법 5(클래스 failable initialize 상속)iOS프로그래밍기초 2024. 10. 10. 16:35
1. class , object , instance


- 스위프트에서는 프로퍼티와 메소드로 말함
- 스위프트에서는 인스턴스만들때 new 안씀
2. property

- 인스턴스 메서드와 타입 메서드 2가지가 있다.
class Man{ //var age : Int // error , stored property는 초기값 없이 선언안됨 var age : Int = 0 // 1번 초기값을 주기 var weight : Double = 0.0 }- 프로퍼티는 2종류가 있다.
- 스토어드 프로퍼티는 초기값이 있어야 한다
- 또는 옵셔널을 주워야함
class Man{ var age1 : Int? // 2번 옵셔널 변수로 만들어서 초기값을 자동으로 nil을 주기 var age2 : Int! // var weight : Double = 0.0 }- 옵셔널 변수를 선언해 자동으로 nil값을 주기
3. 클래스 선언 , 인스턴스 정의
class Man{ var age : Int = 1 var weight : Double = 3.5 func display() { print("나이=\(age), 몸무게=\(weight)") } } //var kim : Man //kim.age //Variable 'kim' used before being initialized var kim : Man = Man() print(kim.age) kim.display()- kim 은 Man 클래스 타입으로 함 // kim : Man
- 주석에서는 kim이 age에 접근할려고 하면 에러가뜸 - 이니셜라이즈를 사용해라
- 눈에 보이지 않는 생성자 디폴트 이니셜라이즈가 있음
- 이니셜라이즈를 통해서 kim을 만듬


4. 언어들 마다 클래스를 만드는 형태
#include <iostream> class MyClass { public: int x; MyClass(int val) { x = val; } }; int main() { MyClass obj(10); std::cout << "Value of x: " << obj.x << std::endl; return 0; }class MyClass { int x; MyClass(int val) { x = val; } } public class Main { public static void main(String[] args) { MyClass obj = new MyClass(10); System.out.println("Value of x: " + obj.x); } }using System; class MyClass { public int x; public MyClass(int val) { x = val; } } class Program { static void Main(string[] args) { MyClass obj = new MyClass(10); Console.WriteLine("Value of x: " + obj.x); } }class MyClass { constructor(val) { this.x = val; } } const obj = new MyClass(10); console.log("Value of x: " + obj.x);class MyClass: def __init__(self, val): self.x = val obj = MyClass(10) print("Value of x:", obj.x)class MyClass { var x: Int init(val: Int) { x = val } } let obj = MyClass(val: 10) print("Value of x: \(obj.x)")5. 인스턴스 메소드 , 클래스 메소드
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.cM //error // kim.scM() //error // Static member 'scM' cannot be used on instance of type 'Man' // 클래스 메소드는 인스턴스가 아니라 클래스가 사용하는 메소드 kim.display() //인스턴스 메서드는 인스턴스가 호출 Man.cM() //클래스 메서드는 클래스가 호출 Man.scM() //클래스 메서드는 클래스가 호출- 메소드의 종류 2가지, 인스턴스 메소드 , 클래스 메소드
- 클래스 메소드는 클래스에서 호출
- 인스턴스 메소드는 인스턴스가 호출

- 클래스 메소드는 2종류로 class 를 붙인것 , static을 붙인것 2개다
- class 키워드를 사용한 메소드는 자식클래스에서 오버라이드가 가능하다.
- class를 쓰면 오버라이드 가능 , static을 사용하면 오버라이드 불가능
6. initalizer
class Man{ var age : Int = 1 var weight : Double = 3.5 init(yourAge: Int, yourWeight : Double){ age = yourAge weight = yourWeight } //designated initializer func display(){ // 인스턴스 메소드 print("나이=\(age), 몸무게=\(weight)") } } // var kim : Man = Man(). //error // Missing arguments for parameters 'yourAge', 'yourWeight' in call var kim : Man = Man(yourAge: 10, yourWeight: 30.5) kim.display()- 이니셜라이즈 , 생성자는 함수이다.
- 이니셜라이즈를 직접 작성하고 , 파라미터를 만들면 , 인스턴스 정의시 () 빈값을 넣으면 에러.
- 아규먼트 레이블등 과 같이 쓰면서 아규먼트를 넣어서 인스턴스를 만들어야함

- 모든 프로퍼티를 다 초기화하는 생성자를 designated initializer. 데지그나이트 이니셜라이저 라고함
- 프로퍼티 하나만 초기화 하면 designated initializer 라고 안함
var kim = Man.init(yourAge: 10, yourWeight: 30.5) kim.display()- init 함수를 기본으로 사용하고 있는거임 // 평소에 뺄 수 있음
7. self

class Man{ var age : Int = 1 var weight : Double = 3.5 init(age: Int, weight : Double){ self.age = age self.weight = weight } func display(){ print("나이=\(age), 몸무게=\(weight)") } } var kim = Man(age: 10, weight: 30.5) // Cannot assign to value: 'age' is a 'let' constant // Cannot assign to value: 'weight' is a 'let' constant // self 없이 하면 지역변수를 가리키는게 당연 kim.display()- 스위프트에서 인스턴스를 가리키는 건 self , 다른언어의 this

8.

이런것도 있는데 일단 지나감 9. 메소드 오버라이딩 method overloading
class Man{ var age : Int = 1 var weight : Double = 3.5 init(age: Int, weight : Double){ // 첫번째 생성자 self.age = age self.weight = weight } init(age: Int){. // 두번째 생성자 self.age = age } func display(){ print("나이=\(age), 몸무게=\(weight)") } } var kim = Man(age: 10, weight: 30.5) var lee = Man(age: 3) lee.display() kim.display()- 생성자가 여러개 있는 코드예제
- 매개변수 종류나, 개수가 다른 init 함수가 여러개 있음

UIImage
https://developer.apple.com/documentation/uikit/uiimage
UIImage | Apple Developer Documentation
An object that manages image data in your app.
developer.apple.com

- 애플에서 만든 UIImage 는 사용자를 위해 수많은 init() 을 overriding 해놨다.
10. failable initializers(실패 가능한 생성자: init? ) // 아주 중요함 , 어려움

- init?() , init!() !는 잘안씀
- 생성자가 실행되지않는 오류상황에 nil을 리턴
class Man{ var age : Int var weight : Double func display(){ print("나이=\(age), 몸무게=\(weight)") } init?(age: Int, weight : Double){ // failable initializer if age <= 0 { return nil } else { self.age = age } self.weight = weight } } var kim : Man = Man(age:10, weight:20.5) //error //Value of optional type 'Man?' must be unwrapped to a value of type 'Man' kim.display() var lee : Man = Man(age:0, weight:3.5) //error lee.display()- ex) Student() 생성시 age가 0보다 낮을때 등을 조건으로 nil 을 리턴
- 일반 인스턴스가 안만들어짐 , 옵셔널로 감싸진 인스턴스가 생성됨
- 옵셔널을 풀어주는 게 필요함
var kim : Man = Man(age:10, weight:20.5)! //! kim.display() var lee : Man = Man(age:0, weight:3.5)! //! lee.display()- 강제로 풀기. 좋은 방법은 아님
var kim : Man = Man(age:10, weight:20.5)! //!을 붙이기. kim.display() var lee : Man = Man(age:0, weight:3.5)! //age가 0임 nil을 출력 // 크레시가 나며 앱이 다운됨 lee.display()- 제대로 사용해라.

- 옵셔널을 푸는 4가지 방법
- 2번 형태가 1번의 간소화 형태를 띄우며 가장 많이 사용함
- 3,4는 언젠가 크래시가 나게됨
1번)
var lee : Man? = Man(age:0, weight:3.5) // Man? if let lee { // if let 형 lee.display() // lee가 nil이 아닐때만 실행해라. }2번)
if let lee = Man(age:0, weight:3.5){ // Man에서 어차피 옵셔널이 나오니 바로 if let으로 보냄 lee.display() }<전체코드 주석설명>
// Man 클래스 정의 class Man { var age: Int // 나이를 저장하는 속성 var weight: Double // 몸무게를 저장하는 속성 // 객체의 속성(나이, 몸무게)을 출력하는 메서드 func display() { print("나이=\(age), 몸무게=\(weight)") } // failable initializer (실패 가능한 생성자) // 나이와 몸무게 값을 받아서 초기화하며, 값이 적절하지 않으면 nil을 반환 init?(age: Int, weight: Double) { // 나이와 몸무게가 0 이하이면 객체 생성을 실패로 처리하고 nil을 반환 if age <= 0 || weight <= 0.0 { return nil // 객체 생성 실패 } else { // 나이와 몸무게가 정상적이면 속성을 초기화 self.age = age self.weight = weight } } } // 객체 생성 및 조건에 따른 처리 // if let 구문을 사용해 Man 객체를 생성하고 성공 여부를 확인 if let lee = Man(age: 1, weight: 0.0) { // 만약 객체가 정상적으로 생성되면 display 메서드를 호출하여 속성 출력 lee.display() } else { // 객체 생성 실패 시 아무것도 출력되지 않음 (예: 나이가 1이지만 몸무게가 0.0이므로 객체 생성 실패) // 이 경우에는 else 블록이 없어 출력하지 않음 }11. 클래스 상속

- 객체 지향 언어에서 가장 많이 사용하는것은 상속이다.

- 스위프트의 상속은 부모 : 자식 형태를 가짐
- 상속은 클래스만 가능한다.
- 부모하나만 상속가능 하다.
- , 후 여러개 더 있으면 부모클래스가아닌 프로토콜이다.
- 프로토콜은 여러개가 상속 가능하다.
class Man{ var age : Int = 1 var weight : Double = 3.5 init(age: Int, weight : Double){ // 첫번째 생성자 self.age = age self.weight = weight } func display(){ print("나이=\(age), 몸무게=\(weight)") } } class Student : Man { // Man은 super or 부모클래스 } var lee : Student = Student(age: 20, weight: 70.5) lee.display() var kim = Man(age: 10, weight: 30.5) kim.display()- Student 클래스는 아무것도 없는 빈 클래스지만 상속을 통해 부모의 모든 요소를 받아왔다 - 실제로 못받는 값들도 있음
12. superclass 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) // 부모age에 자식age값넣기 }//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()- Student 자식클래스가 부모클래스와 다르게 name을 사용하고 싶음
13. 오버라이딩 overriding. , override 키워드

- 부모의display() 를 자식클래스 에서 똑같이 쓸려고 했더니 나온 에러
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 override func display() { //오버라이드 print("이름=\(name), 나이=\(age), 몸무게=\(weight)") } init(age: Int, weight : Double, name : String){ self.name = name super.init(age:age, weight:weight) } } var lee : Student = Student(age:20,weight:65.2,name:"홍길동") lee.display()- 스위프트에서는 자식클래스안 에서 override 키워드를 사용해서 오버라이딩을 구현한다.
- 오버라이드는 객체지향 언어에서 반드시 필요
<전체설명>
// 부모 클래스 Man 정의 class Man { var age: Int // 나이를 저장하는 속성 var weight: Double // 몸무게를 저장하는 속성 // 부모 클래스의 메서드. 나이와 몸무게를 출력함. func display() { print("나이=\(age), 몸무게=\(weight)") } // 부모 클래스의 생성자. 나이와 몸무게 값을 초기화함. // designated initializer: 모든 프로퍼티를 초기화하는 생성자 init(age: Int, weight: Double) { self.age = age // 전달받은 나이 값을 속성에 저장 self.weight = weight // 전달받은 몸무게 값을 속성에 저장 } } // 자식 클래스 Student는 Man 클래스를 상속받음 class Student: Man { var name: String // 이름을 저장하는 속성 // 부모 클래스의 display 메서드를 오버라이드 (재정의)하여 이름까지 출력함. override func display() { // 오버라이드된 메서드에서는 부모 클래스의 메서드를 덮어써서 자식 클래스에 맞게 수정할 수 있음 print("이름=\(name), 나이=\(age), 몸무게=\(weight)") } // 자식 클래스의 생성자. 이름, 나이, 몸무게를 모두 초기화함. // 이니셜라이저에서 부모 클래스의 초기화 메서드(super.init)를 호출하여 상속받은 속성들을 초기화해야 함. init(age: Int, weight: Double, name: String) { self.name = name // 전달받은 이름 값을 저장 super.init(age: age, weight: weight) // 부모 클래스의 초기화 메서드 호출 // 부모 클래스의 속성(age, weight)을 초기화하기 위해 반드시 super.init을 호출해야 함 // 'super.init'을 호출하지 않으면 에러 발생 (부모 클래스 속성이 초기화되지 않기 때문) } } // Student 객체 생성 var lee: Student = Student(age: 20, weight: 65.2, name: "홍길동") // lee.display() 호출 시 오버라이드된 메서드가 실행됨 lee.display() // 출력: 이름=홍길동, 나이=20, 몸무게=65.2 // 추가 설명: // 1. 인스턴스 생성 시 new 키워드가 필요 없음 // Swift는 다른 언어들과 달리 객체를 생성할 때 new를 사용하지 않음. // 예: var lee: Student = Student() // new 키워드를 쓰지 않음 // 2. self // self는 현재 인스턴스를 가리킴. 다른 언어의 this와 동일한 역할을 함. // self.age = age // 생성자에서 전달받은 매개변수 age를 인스턴스의 age에 할당 // 3. 오버라이드 (override) // 자식 클래스에서 부모 클래스의 메서드를 재정의하기 위해 override 키워드를 사용함. // 부모의 메서드를 오버라이드하는 경우, 반드시 override 키워드를 사용해야 함. // Swift는 이 키워드를 통해 의도적인 재정의를 명시적으로 요구함. // 4. 클래스 메서드와 인스턴스 메서드 // display()는 인스턴스 메서드로, 인스턴스를 통해 호출됨. // 클래스 메서드는 static이나 class 키워드를 사용하여 정의되며, 인스턴스가 아닌 클래스 자체에서 호출 가능. // 예: class func classMethod() { ... } // 클래스 메서드는 클래스에서 직접 호출, 인스턴스 메서드는 인스턴스를 통해 호출됨.'iOS프로그래밍기초' 카테고리의 다른 글
[9주차] xcode, 시뮬레이터 예제들 (6) 2024.10.31 [7주차] Xcode 사용법 및간단한 iOS앱 개발 (1) 2024.10.17 [5주차] Swift 문법 4(일급시민 클로저 기초) (1) 2024.10.09 [4주차] Swift 문법 3 (1) 2024.09.26 [3주차] Swift 문법 2 (0) 2024.09.19