DAY 12
클래스(class)
클래스 vs 객체 vs 인스턴스
클래스로부터 객체를 만들고 만들어진 실제 메모리상에 할당된 객체를 instance 라고 함
인스턴스(Instance)
소프트웨어 애플리케이션을 개발하는 데 사용되는, 쉽게 사용할 수 있으며 재사용할 수 있는 기능을 가진 모듈
객체의 구성
- 데이터 변수(data variable) or 속성(property)
- 함수 or 메서드(method)
Theory | Swift | Java | C++ |
---|---|---|---|
Data | Property | Field | Member variable |
Operation | Method | Method | Member function |
클래스
Structures and Classes
구조체와 열거형은 Value Types, 클래스는 Reference Types
일반적인 스위프트 가이드라인에서는 구조체를 사용하는 것을 더 추천한다
클래스에는 있지만, 구조체에는 없는 기능
- Inheritance
- Type casting
- Deinitializers
클래스의 기본 구조
class 새로운 클래스 이름: 부모 클래스 {
// property
// instance method
// type method(class method)
}
instance method
는 객체가 호출하는 메서드를 정의
type method
는 클래스가 호출하는 메서드를 정의
property
조건
- 초기값이 있거나
- init을 이용하여 초기화
- 옵셔널 변수(상수)로 선언
property는 stored property 와 computed property 가 있음
stored property
class Man {
var age: Int
var weight: Double
}
다음과 같이 실행하면 property의 조건을 만족하지 않기 때문에 오류가 발생한다
stored property에 초기값을 주는 3가지 방법
// 1. 값을 직접 지정해준다
class Man {
var age: Int = 1
var weight: Double = 3.5
}
// 2. 옵셔널 변수로 선언한다 (Optional 변수는 `nil`로 자동 초기화 되기 때문)
class Man {
var age: Int?
var weight: Double!
}
// 3. initializer로 초기화
class Man {
var age: Int
var weight: Double
init() {
age = 1
weight = 3.5
}
}
computed property
computed property(계산 프로퍼티)는 property가 설정되거나 검색되는 시점에서 계산 또는 파생된 값
클래스, 구조체, 열거형에서 사용되며 stored property와 달리 저장 공간을 갖지 않고 다른 stored property의 값을 읽어 연산을 실행하거나, property로 전달받은 값을 다른 property에 저장한다
때문에 항상 var
로 선언되어야 함
또한, 타입 추론을 통해 형식을 알 수 없어서, 선언할 때 자료형을 명시해야 함
- 값을 리턴하는 게터(getter) method
- 값을 대입하는 세터(setter) 메서드
getter
var manAge: Int {
get {
return age-1
}
}
어떤 stored property의 값을 연산해서 return
할 것인지, return
구문이 항상 존재해야 함
manAge
는 계산 프로퍼티로 저장 프로퍼티 age
의 값에서 1을 뺀 값으로 하겠다는 것을 뜻함
setter
가 없으면 get { }
은 생략할 수 있으며 변경하지 않더라도 var
로 선언해야 함
var manAge: Int {
return age-1
}
setter
parameter로 받은 값을 어떤 stored property에 어떻게 설정할 것인지 구현
setter
가 있으면 get{ }
는 생략할 수 없다
매개변수명은 newValue
가 기본이며, parameter를 받을 때 type을 명시해주지 않는 이유는 이미 computed property를 선언할 때 타입을 반드시 명시해줬기 때문이다
set(newValue) {
age = newValue + 1
}
Shorthand Setter Declaration
setter
의 매개변수명이 newValue
인 경우에만 이렇게 (newValue)
생략 가능
set {
age = newValue + 1
}
getter와 setter를 갖는 computed property manAge
var manAge: Int {
get { return age-1 }
set { age = newValue + 1}
}
Method
instance method 와 type method 가 있다
instance method
인스턴스 메서드 는 인스턴스에서 동작
func ~~()
처럼, func
keyword 앞에 아무것도 없는 경우 instance method 임
class Man {
var age: Int = 1
var weight: Double = 3.5
func display() {
print("나이=\(age), 몸무게=\(weight)")
}
}
instance 생성하기
var 인스턴스명 : 클래스명 = 클래스명()
var 인스턴스명 = 클래스명()
()
는 default initializer(기본 생성자) 를 나타낸다
다음과 같이 사용할 수 있다
var kim: Man = Man()
kim.display()
// instance.instance method
print(kim.age)
// instance.property
type method(class method)
type method 는 클래스 레벨에서 동작하는 것으로, 클래스의 새로운 인스턴스를 생성하는 것과 같은 동작
instance method 와 동일한 방법으로 선언하지만, class
나 static
키워드를 앞에 붙여서 선언함
class
키워드로 만든 class method 는 자식 클래스에서 override
가능
class Man {
var age: Int = 1
var weight: Double = 3.5
class func tm() {
print("class method")
}
static func stm() {
print("class method")
}
}
Man.tm()
Man.stm()
인스턴스 초기화하기 : init()
클래스, 구조체, 열거형 인스턴스가 생성되는 시점에서 해야 할 초기화 작업
생성자
인스턴스가 만들어지면서 자동 호출된다
init() { }
designated initializer : 모든 property 를 다 초기화시키는 생성자
소멸자
인스턴스가 사라질 때 자동 호출
deinit{}
JAVA 언어에서 배운것과 동일하게 생성자를 하나라도 직접 만들면, default initializer는 사라진다
self
현재 클래스 내 method 나 property 를 가리킬 때 method, property 앞에 self.
을 붙임
매개변수 명과 property 명이 동일한 경우에는 구분해주기 위하여 반드시 써야함
init(age: Int, weight: Double) {
self.age = age
self.weight = weight
}
method overloading : 생성자 중첩
매개변수의 개수와 자료형이 다른 같은 이름의 함수를 여러개 정의한 것
매개변수가 다른 두 생성자를 통해 두가지 방법으로 인스턴스를 만들 수 있다
init(age: Int, weight: Double) {
self.age = age
self.weight = weight
}
init(age: Int) {
self.age = age
}
failable initializer (실패 가능한 생성자: init?)
init?(named: String)
init?
로 만든 인스턴스는 옵셔널형으로 만들어져서, 사용하려면 옵셔널을 언래핑해야 함
오류 상황에 nil
을 리턴하는 조건문이 있기 때문임 return nil
class Man {
var age: Int
var weight: Double
init?(age: Int, weight: Double) {
if age <= 0 {
return nil
}
else {
self.age = age
}
self.weight = weight
} // failable initialize
}
var kim: Man = Man(age:10, weight:20.5)
var lee: Man = Man(age:0, weight:3.5)
실행시키면, 다음과 같은 오류가 발생한다
error: value of optional type 'Man?' must be unwrapped to a value of type 'Man'
이는, 인스턴스를 생성할 때 실행되는 생성자가 Optional형이기 때문에 unwrapping을 하지 않아 생기는 오류이다
이는 다음과 같은 몇가지 방법으로 해결할 수 있다
// 1. 옵셔널 형으로 선언 후 옵셔널 바인딩
var kim: Man? = Man(age:1, weight:3.5)
if let kim1 = kim {
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번 방식으로 강제 언래핑 하는 방법은 위험함
만약 age <= 0
일 때, init?
은 nil
을 반환하는데, 이때 강제 언래핑을 하고 display()
를 호출하면 crash가 발생함
댓글