iOS 6주차 (10.10)
설계도인 클래스로부터 만들어진 실체를 객체라 하고 실제로 사용 중인 객체를 인스턴스라 합니다.
인스턴스(instance)란 실제로 메모리에 할당된 객체(object)입니다.
클래스 vs. 인스턴스(객체)
class는 인스턴스(객체)의 청사진이나 설계도
int x;
Student han; //C++
- 클래스 인스턴스;
var Kim = Man() //Swift
- var 인스턴스 = 클래스();
Swift 클래스 선언하기
클래스의 기본 구조 class 새로운 클래스 이름 : 부모 클래스 {
// 프로퍼티
// 인스턴스 메서드
// 타입(type) 메서드(클래스 메서드)
}
“프로퍼티” 부분은 클래스 내에 포함되는 변수(var)와 상수(let)를 정의
“인스턴스 메서드”는 객체가 호출하는 메서드를 정의
“타입 메서드”는 클래스가 호출하는 메서드를 정의
클래스에 저장 프로퍼티(stored property) 추가
- 초기값이 있거나
- nit을 이용해서 초기화하거나
- 옵셔널 변수(상수)로 선언(자동으로 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되어 있습니다.

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?로 만든 인스턴스는 옵셔널형으로 만들어져서, 사용하려면 옵셔널을 언래핑해야 해서 위의 예제에서 제일 마지막에 “!”가 있음.
사용 이유
- 유효성 검사: 초기화 시 입력값의 유효성을 검사하고, 유효하지 않을 경우 nil을 반환할 수 있습니다.
- 안전성: 객체가 성공적으로 생성되었는지 여부를 확인할 수 있어, 이후 코드에서 안전하게 사용할 수 있습니다.
- 에러 처리: 초기화 실패를 통해 에러 처리를 간편하게 할 수 있습니다.
인스턴스 생성과 옵셔널 인스턴스의 방법은 그리 좋지못한 예시들 입니다. 강제 언래핑시 문제가 발생할 수 있음(crash)
옵셔널 형으로 선언하거나 인스턴스 생성과 동시에 옵셔널 바인딩 하는 방식을 추천