카테고리 없음

iOS 6주차 (10.10)

k0223 2024. 10. 10. 16:49

설계도인 클래스로부터 만들어진 실체를 객체라 하고 실제로 사용 중인 객체를 인스턴스라 합니다.

 

인스턴스(instance)란 실제로 메모리에 할당된 객체(object)입니다.

 

클래스 vs. 인스턴스(객체)

class는 인스턴스(객체)의 청사진이나 설계도

int x;

Student han; //C++

  • 클래스 인스턴스;

var Kim = Man() //Swift 

  • var 인스턴스 = 클래스();

Swift 클래스 선언하기

클래스의 기본 구조 class 새로운 클래스 이름 : 부모 클래스 {

        // 프로퍼티

        // 인스턴스 메서드

        // 타입(type) 메서드(클래스 메서드)

}

“프로퍼티” 부분은 클래스 내에 포함되는 변수(var)와 상수(let)를 정의

“인스턴스 메서드”는 객체가 호출하는 메서드를 정의

“타입 메서드”는 클래스가 호출하는 메서드를 정의

 

클래스에 저장 프로퍼티(stored property) 추가

  1. 초기값이 있거나
  2. nit을 이용해서 초기화하거나
  3. 옵셔널 변수(상수)로 선언(자동으로 nil로 초기화)

위의 장면은 초기값이 없기에 오류가 생겼습니다.

 

클래스로부터 인스턴스을 만드는 방법.

 

C++, java, C#, Python, Swift에서 클래스로 부터 객체를 만드는 예시들 입니다.

C++

#include <iostream>
using namespace std;

class Dog {
public:
    void bark() {
        cout << "Woof!" << endl;
    }
};

int main() {
    Dog myDog; // 객체 생성
    myDog.bark(); // 메서드 호출
    return 0;
}

Java

class Dog {
    void bark() {
        System.out.println("Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog(); // 객체 생성
        myDog.bark(); // 메서드 호출
    }
}

C#

using System;

class Dog {
    public void Bark() {
        Console.WriteLine("Woof!");
    }
}

class Program {
    static void Main() {
        Dog myDog = new Dog(); // 객체 생성
        myDog.Bark(); // 메서드 호출
    }
}

Python

python

class Dog:
    def bark(self):
        print("Woof!")

my_dog = Dog()  # 객체 생성
my_dog.bark()   # 메서드 호출

Swift

class Dog {
    func bark() {
        print("Woof!")
    }
}

let myDog = Dog() // 객체 생성
myDog.bark()     // 메서드 호출

 

클래스(class or type) 메서드

클래스명.클래스메서드()

타입 메서드 또는 클래스 메서드는 클래스 레벨에서 동작

타입 메서드는 인스턴스 메서드와 동일한 방법으로 선언하지만 class 나 static 키워드를 앞에 붙여서 선언

class키워드로 만든 클래스 메서드는 자식 클래스에서 override가능

 

init()을 하나라도 직접 만들면 기본적으로 만들어지는 눈에 안보이는 default initializer는 사라집니다.

때문에 직접 값을 넣어줘야됩니다.

 

self

현재 클래스 내 메서드나 프로퍼티를 가리킬 때 메서드나 프로퍼티 앞에 self.을 붙임

아래 소스에서는 self를 붙이거나 생략해도 됨

옆의 소스에서는 매개변수와 구분하기 위해 반드시 써야함

 

C++, java, C#, Python, Swift 중 self나 this을 사용하는 예제입니다.

C++

#include <iostream>
using namespace std;

class Dog {
public:
    string name;

    Dog(string name) {
        this->name = name; // this 사용
    }

    void bark() {
        cout << name << " says Woof!" << endl;
    }
};

int main() {
    Dog myDog("Buddy"); // 객체 생성
    myDog.bark(); // 메서드 호출
    return 0;
}

Java

class Dog {
    String name;

    Dog(String name) {
        this.name = name; // this 사용
    }

    void bark() {
        System.out.println(name + " says Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog("Buddy"); // 객체 생성
        myDog.bark(); // 메서드 호출
    }
}

C#

using System;

class Dog {
    public string Name;

    public Dog(string name) {
        this.Name = name; // this 사용
    }

    public void Bark() {
        Console.WriteLine(Name + " says Woof!");
    }
}

class Program {
    static void Main() {
        Dog myDog = new Dog("Buddy"); // 객체 생성
        myDog.Bark(); // 메서드 호출
    }
}

Python

python

class Dog:
    def __init__(self, name):
        self.name = name  # self 사용

    def bark(self):
        print(f"{self.name} says Woof!")

my_dog = Dog("Buddy")  # 객체 생성
my_dog.bark()          # 메서드 호출

Swift

class Dog {
    var name: String

    init(name: String) {
        self.name = name // self 사용
    }

    func bark() {
        print("\(name) says Woof!")
    }
}

let myDog = Dog(name: "Buddy") // 객체 생성
myDog.bark()                   // 메서드 호출

 

method overloading : 생성자 중첩

매개변수의 개수와 자료형이 다른 같은 이름의 함수를 여러 개 정의

매개변수가 다른 두 생성자를 통해 두가지 방법으로 인스턴스를 만들 수 있습니다.

 

Swift는 앱에서 이미지 데이터를 관리하는 클래스인 UIImage는 15개의 init()가 overloading되어 있습니다.

https://developer.apple.com/documentation/uikit/uiimage

 

Swift에서는 superclass 클래스 부모 classs, subclass 클래스 자식 class라고 합니다.

 

C++, java, C#, Python, Swift 의 상속 예제들 입니다.

C++

#include <iostream>
using namespace std;

class Animal {
public:
    void speak() {
        cout << "Animal speaks!" << endl;
    }
};

class Dog : public Animal { // Animal 클래스를 상속받음
public:
    void bark() {
        cout << "Woof!" << endl;
    }
};

int main() {
    Dog myDog; // 객체 생성
    myDog.speak(); // 부모 클래스 메서드 호출
    myDog.bark();  // 자식 클래스 메서드 호출
    return 0;
}

Java

class Animal {
    void speak() {
        System.out.println("Animal speaks!");
    }
}

class Dog extends Animal { // Animal 클래스를 상속받음
    void bark() {
        System.out.println("Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog(); // 객체 생성
        myDog.speak(); // 부모 클래스 메서드 호출
        myDog.bark();  // 자식 클래스 메서드 호출
    }
}

C#

using System;

class Animal {
    public void Speak() {
        Console.WriteLine("Animal speaks!");
    }
}

class Dog : Animal { // Animal 클래스를 상속받음
    public void Bark() {
        Console.WriteLine("Woof!");
    }
}

class Program {
    static void Main() {
        Dog myDog = new Dog(); // 객체 생성
        myDog.Speak(); // 부모 클래스 메서드 호출
        myDog.Bark();  // 자식 클래스 메서드 호출
    }
}

Python

class Animal:
    def speak(self):
        print("Animal speaks!")

class Dog(Animal):  # Animal 클래스를 상속받음
    def bark(self):
        print("Woof!")

my_dog = Dog()  # 객체 생성
my_dog.speak()  # 부모 클래스 메서드 호출
my_dog.bark()   # 자식 클래스 메서드 호출

Swift

class Animal {
    func speak() {
        print("Animal speaks!")
    }
}

class Dog: Animal { // Animal 클래스를 상속받음
    func bark() {
        print("Woof!")
    }
}

let myDog = Dog() // 객체 생성
myDog.speak()     // 부모 클래스 메서드 호출
myDog.bark()      // 자식 클래스 메서드 호출

 

 

Swift

class 자식:부모 {

}

  • 부모 클래스는 하나만 가능
  • 콜론 다음이 여러 개이면 나머지는 프로토콜
  • 부모가 없으면 프로토콜이 올수도 있음(여러개도 가능)

 

 

super : 부모 메서드 호출 시 사용

 

override : 부모와 자식에 같은 메서드가 있으면 자식 우선

  • 부모와 자식에 display()라는 메서드가 있어서 Student클래스는 display() 메서드가 두 개임 
  • Student클래스의 인스턴스 lee가 display()를 호출할 때, 자식클래스가 새로 만든 display() 메서드가 우선적으로
    호출되려면func 앞에 override키워드 사용합니다.

 

failable initializers(실패 가능한 생성자: init?)

 

Swift에서 failable initializers는 객체를 초기화할 수 없는 경우 nil을 반환할 수 있는 초기화 메서드입니다.

이는 객체 생성이 항상 성공하지 않을 수 있는 경우에 유용합니다.

예를 들어, 입력값이 유효하지 않거나 특정 조건을 만족하지 않을 때 객체를 생성하지 않도록 하고 싶을 때 사용합니다.

  • let myImage: UIImage = UIImage(named: "apple.png")! //느낌표가 왜 있지?
  • apple.png파일이 없으면 인스턴스를 만들 수 없고 nil
  • nil값도 저장할 수 있으려면 init다음에 “?”를 하며 옵셔널 값이 리턴됨
  • init?(named name: String) // failable initializers
  • init?로 만든 인스턴스는 옵셔널형으로 만들어져서, 사용하려면 옵셔널을 언래핑해야 해서 위의 예제에서 제일 마지막에 “!”가 있음.

사용 이유

  1. 유효성 검사: 초기화 시 입력값의 유효성을 검사하고, 유효하지 않을 경우 nil을 반환할 수 있습니다.
  2. 안전성: 객체가 성공적으로 생성되었는지 여부를 확인할 수 있어, 이후 코드에서 안전하게 사용할 수 있습니다.
  3. 에러 처리: 초기화 실패를 통해 에러 처리를 간편하게 할 수 있습니다.

 

인스턴스 생성과 옵셔널 인스턴스의 방법은 그리 좋지못한 예시들 입니다. 강제 언래핑시 문제가 발생할 수 있음(crash)

옵셔널 형으로 선언하거나 인스턴스 생성과 동시에 옵셔널 바인딩 하는 방식을 추천