- 클래스를 이해하기 전에 먼저 객체 지향 프로그램에 대해서 이해가 필요하다.
- 해당 내용은 아래 링크에 자세하게 다루었다.
- 정리하자면 객체 지향 프로그래밍의 특징은 아래와 같다.
- 모든 것을 객체로 취급한다.
- 객체는 실 세계에 존재하거나 생각할 수 있는 것들을 통틀어서 이야기한다.
- 클래스로 정의되고 클래스의 속성(변수, 데이터, 프로퍼티)와 클래스의 메소드 형태로 구성된다.
- 클래스의 메소드는 행위를 나타낸다.
- 클래스 정의와 객체 생성 방법
- 클래스 정의 : class [클래스 명] { 클래스의 속성 및 메소드 }클래스 정의
class Rectangle {
// 사각형의 가로, 세로 길이에 대한 속성을 정의
// 사각형의 넓이에 대한 메소드를 정의
} - 객체 생성 : [클래스 명]()객체 생성
var rect = Rectangle() // 새로운 객체 대입 가능
rect = Rectangle()
let rect1 = Rectangle() // 새로운 객체 대입 불가능 - 소스코드 파일과 클래스의 관계
- 클래스와 프로퍼티
- 프로퍼티는 객체의 데이터를 나타내며 값을 저장하고 읽는 역할을 한다.
- 프로퍼티 종류 (저장 프로퍼티, )
- 저장 프로퍼티
- 데이터를 저장하는 용도로 쓰인다.
- 데이터를 읽고 쓰는 역할을 한다.
- 객체 생성 시 초기화하며, 초기화하는 방법이 필요하다.
- 저장 프로퍼티 정의 및 사용 예시는 아래와 같다.저장 프로퍼티 예시
// 저장 프로퍼티 정의
class MyClass{
// 초기값을 설정한 프로퍼티
var intProperty = 0
// 초기값을 설정하지 않은 프로퍼티
var floatProperty : Float?
// 초기값 설정이 반드시 필요한 프로퍼티
var strProperty : String = "Test"
}
// 저장 프로퍼티 사용
var obj = MyClass() // 객체 생성
// 저장 프로퍼티에 값을 저장
obj.intProperty = 10
obj.floatProperty = 3.1
// 저장 프로퍼티에 값을 사용
let val = obj.floatProperty
print("val = \(val)") // val = 3.1 출력 - 계산 프로퍼티
- 데이터를 저장하지 않는다.
- 프로퍼티 읽기/쓰기 코드를 작성한다.(set/get)
- 읽기전용은 가능하고 쓰기 전용은 사용할 수 없다.(get만 존재)
- 계산 프로퍼티 쓰기에서 설정 값은 반드시 한개만 가능하다.(set에 파라미터는 한개만 가능하다.)
- set에 들어가는 기본 파라미터 명은 newValue 이며, 그대로 사용해도 되고, 변경도 가능하다.
- 계산 프로퍼티 정의 및 사용 예는 아래와 같다.계산 프로퍼티 예시
// 계산 프로퍼티 정의
class Rectangle {
var width = 0
var height = 0
// 계산 프로퍼티 정의 (읽기 전용)
var area : Int {
get {
return (width * height)
}
}
}
// 계산 프로퍼티 사용
var rect = Rectangle()
rect.width = 10
rect.height = 20
print(rect.area) // 200 출력 - 프로퍼티 변경 감시 : 프로퍼티가 객체 생성 후에 변경이 될 경우 변경 전의 값과 변경 후의 값을 확인할 수 있다.
- 프로퍼티 변경 전 : willSet
- 프로퍼티 변경 후 : didSet
- 프로퍼티 변경 감시 사용 예시는 아래와 같다.프로퍼티 감시 예시
class Rectangle {
var height : Int = 0 {
willSet {
print("사각형 높이 변경 예정 : \(newValue)")
}
didSet {
print("사각형 높이 변경 완료. 이전 값 : \(oldValue)")
}
}
} - 프로퍼티의 늦은 초기화 : 보통은 객체 생성과 동시에 프로퍼티를 초기화를 하지만 프로퍼티를 사용할 때 초기화하는 방법이 있다.
- 프로퍼티의 늦은 초기화하는 lazy 키워드를 앞에 붙여서 정의한다.
- 사용 예시는 아래와 같다.프로퍼티의 늦은 초기화
class Person {
lazy var phone = Phone()
}
let john = Person()
john.phone // 이 때 초기화가 된다. - 클래스와 메소드
- 클래스 내에서 메소드(함수)는 어떤 동작을 할지 정의한다.
- 메소드의 종류
- 인스턴스 메소드
- 객체 생성 후 사용해야한다. (객체를 생성하지 않고는 사용할 수 없다.)
- 객체의 데이터(프로퍼티) 접근이 가능하다.
- 타입 메소드
- 객체를 생성하지 않고 사용 가능하다.
- 객체의 데이터(프로퍼티) 접근을 할 수 없다.
- 키워드는 static으로 한다.(자세한 내용은 5번에서 다룬다.)
- 이번에 다루는 메소드는 인스턴스 메소드이다.
- 클래스 내에서 메소드 정의 및 사용 예시는 아래와 같다.클래스 내에서 메소드 정의 및 사용
// 클래스 내에 메소드 정의
class Counter {
var count = 0
// 파라미터가 없는 메소드 정의
func increment() {
count += 1
}
// 파라미터가 1개 있는 메소드 정의
func increment(amount : Int) {
count += amount
}
// 파라미터가 2개 있는 메소드 정의
func increment(amount : Int, times : Int) {
count += (amount * times)
}
}
// 정의된 메소드 사용
let counter = Counter()
counter.increment() // count가 1로 증가
counter.increment(amount : 5) // counter가 6으로 증가
counter.increment(amount : 5, times : 3)
// counter가 21로 증가 - self 포인터
- 클래스 내에서 객체 자신을 참조하는 포인터로 프로퍼티 이름과 메소드의 파라미터 이름이 겹칠 때 프로퍼티 이름과 파라미터 이름을 구분하기 위해서 사용한다.self 포인터 사용
class Counter {
var count = 0 // 프로퍼티
// 메소드
func setCount(count : Int) { // 메소드의 파라미터
self.count = count
}
} - 클래스의 타입 메소드와 타입 프로퍼티
- 타입 메소드와 타입 프로퍼티는 모두 객체 생성 없이 사용이 가능하다.
- 타입 메소드는 클래스 내에 정의된 프로퍼티에는 접근할 수가 없다.
- 타입 메소드와 타입 프로퍼티는 static을 앞에 붙여서 정의한다.
- 타입 메소드, 타입 프로퍼티 사용 예시는 아래와 같다.타입 메소드, 타입 프로퍼티 정의 및 사용
// 클래스 내에 타입 메소드, 타입 프로퍼티 정의
class Rectangle {
var width = 0
var height = 0
// 사각형에 대한 정보를 타입 프로퍼티로 정의
static var edge = 4
var area {
get {
return (width * height)
}
}
// 이름에 대한 정보를 타입 메소드로 정의
static func name() -> String {
return "사각형"
}
}
// 정의된 타입 메소드, 타입 프로퍼티 사용
var rect = Rectangle()
rect.width = 10
rect.height = 20
// 타입 프로퍼티 접근
Rectangle.edge // 4
// 타입 메소드 접근
Rectangle.name() // 사각형 - 클래스와 연산자
- 연산자 : 클래스 내에 메소드를 정의하는 것과 동일하게 연산자를 이용하여 해당 클래스 내에서 전용으로 사용되는 연산자를 정의하여 사용할 수 있다. 예) + 연산자에 추가 기능을 더할 수 있다.
- 연산자 정의 시 필요 내용
- 피 연산자의 개수는 파라미터의 개수와 동일하다.
- 단항 연산자는 파라미터 개수가 1개
- 이항 연산자는 파라미터 개수가 2개
- 연산자의 위치
- 앞에 위치 : 전위 연산자 - prefix
- 중간에 위치(기본값) : 중위 연산자 - infix
- 뒤에 위치 : 후위 연산자 - postfix
- 연산자 함수 정의
- 연산자 함수는 타입 메소드로 작성
- 연산자 함수의 이름은 연산자 예) +, -
- 단항 연산자는 연산자 위치 정보가 필요 (prefix, infix, postfix)
- 사용 방법연산자 선언 및 사용
// 클래스 내에 연산자 선언
class Point {
var x : Int
var y : Int
// Initializer
init(x : Int, y : Int) {
self.x = x
self.y = y
}
// 단항 연산자 선언
static prefix func -(point : Point) -> Point {
var another = Point()
another.x = -point.x
another.y = -point.y
return another
}
// 이항 연산자 선언
static func +(left : Point, right : Point) -> Point {
return Point(x : (left.x + right.x), y : (left.y + right.y))
}
}
var point1 = Point(x : 10, y : 20)
point2 = -point1 // Point(x : -10, y : -20)
let result = point1 + point2 // Point(x : 0, y : 0)