객체(인스턴스)란
- 소프트웨어 애플리케이션을 구축하는 블록으로 쉽게 사용하고 재사용 할 수 있는 독립적인 기능 모듈
- 작업을 수행하기 위한 객체나 인스턴스에서 접근되고 호출되는 속성(프로퍼티)과 함수(메서드)로 구성
- 객체를 구성하는 데이터 변수와 함수를 포괄적으로 클래스 멤버라고 함
클래스
- 객체가 생설될 때의 모습 정의
- 메서드, 프로퍼티 정의
클래스 선언
- 새로운 스위프트 클래스를 선언할 때, 새롭게 만드는 클래스가 어떤 부모 클래스에서 파생되었는지 지정
- 클래스에 포함할 프로퍼티와 메서드 정의
// 기본 구문
class 클래스 이름 : 부모 클래스 {
// 프로퍼티
// 인스턴스 메서드
// 타입 메서드
}
- 프로퍼티 : 클래스 내에 포함될 변수나 상수 정의
- 인스턴스 메서드, 타입 메서드 : 클래스에서 호출되는 메서드들과 클래스의 인스턴스 정의
- 특정 작업을 수행하는 클래스 고유의 함수
// BackAccount 클래스
class BackAccount {
}
- 클래스 이름은 각 단어의 첫 번째 문자를 대문자로 선언 (UpperCamelCase)
- 프로퍼티 이름은 lowerCamelCase
클래스에 인스턴스 프로퍼티 추가
- 객체지향 프로그래밍의 핵심 목적 : 데이터 캡슐화
- 데이터 캡슐화 : 클래스에 저장되고 접근될 수 있는 데이터는 오직 해당 클래스 내에 정의된 메서드만을 통해서 접근
- 프로퍼티(인스턴스 변수) : 클래스 내의 캡슐화된 데이터
class BackAccount {
var accountBalance : Float = 0 // 계좌에 남은 잔고
var accountNumber : Int = 0 // 계좌 번호
}
메서드 정의
- 클래스의 성격에 맞는 특정 작업을 수행하기 위해 호출되는 코드 루틴
- 타입 메서드 vs 인스턴스 메서드
- 타입 메서드 : 클래스 레벨에서 동작 (ex. 클래스의 새로운 인스턴스 생성)
- 인스턴스 메서드와 동일하지만, 선언부 앞에 class 키워드가 붙음
- 인스턴스 메서드 : 클래스의 인스턴스에 대한 작업 (ex. 두 개의 프로퍼티에 대한 연산)
- 자신이 속하게 될 클래스의 여는 괄호와 닫는 괄호 안에 선언
- 타입 메서드 : 클래스 레벨에서 동작 (ex. 클래스의 새로운 인스턴스 생성)
class BackAccount {
var accountBalance : Float = 0 // 계좌에 남은 잔고
var accountNumber : Int = 0 // 계좌 번호
// 인스턴스 메서드
func displayBalance(){
print("Number \(accountNumber)")
print("Current balance is \(accountBalance)")
}
// 타입 메서드
class func getMaxBalance(){
return 100000.00
}
}
- 클래스를 설계할 때, 이 클래스에 저장할 수 있는 최대 금액을 알기 위하여 클래스 자신의 타입 메서드를 호출
- 이를 통해 애플리케이션이 클래스 인스턴스를 생성하지 않아도 클래스 자체에서 새로운 고객의 정보 저장 식별 가능
클래스 인스턴스 선언 및 초기화
- 위 클래스를 가지고 작업을 하려면 인스턴스를 생성해야 함
// 인스턴스 생성
var account1 : BankAccount = BankAccount()
클래스 인스턴스 초기화 및 소멸
- 클래스는 인스턴스를 생성하는 시점에 해야 할 초기화 작업이 있을 수 있음
- init 메서드 안에서 구현
- BackAccount 클래스 내에선, 클래스 인스턴스가 생성될 때마다 계좌번호와 잔액 초기화 해야 함
class BackAccount {
var accountBalance : Float = 0 // 계좌에 남은 잔고
var accountNumber : Int = 0 // 계좌 번호
// 초기화
init(number : Int, balance : Float){
accountNumber = number
accountBalance = balance
}
// 인스턴스 메서드
func displayBalance(){
print("Number \(accountNumber)")
print("Current balance is \(accountBalance)")
}
}
// 인스턴스 생성
var account1 = BankAccount(number : 12312312, balance : 400.54)
- 스위프트 런타임 시스템에 의해 클래스 인스턴스가 없어지기 전에 해야 할 정리 작업은 클래스 안에 소멸자(deinitializer)를 구현
class BankAccount {
var accountBalance : Float = 0 // 계좌에 남은 잔고
var accountNumber : Int = 0 // 계좌 번호
// 초기화
init(number : Int, balance : Float){
accountNumber = number
accountBalance = balance
}
// 소멸자
deinit{
// 필요한 작업 수행
}
// 인스턴스 메서드
func displayBalance(){
print("Number \\(accountNumber)")
print("Current balance is \\(accountBalance)")
}
}
// 인스턴스 생성
var account1 = BankAccount(number : 12312312, balance : 400.54)
메서드 호출 및 프로퍼티 접근
- 점 표기법 (dot notation) 이용
- 클래스인스턴스.프로퍼티명
- 클래스인스턴스.인스턴스메서드()
// 인스턴스 변수 값 접근
var balance1 = account1.accountBalance
// 프로퍼티 값 설정
account1.accountBalance = 6789.98
// 메서드 호출
account1.displayBalance()
// 타입 메서드 호출 시 클래스 인스턴스가 아니라 클래스를 호출해야 함
var maxAllowed = BankAccount.getMaxBalance()
저장 프로퍼티 vs 연산 프로퍼티
- 저장 프로퍼티 : 상수나 변수에 담기는 값 (계좌이름, 번호 프로퍼티)
- 연산 프로퍼티 : 프로퍼티에 값을 설정하거나 가져오는 시점에서 어떤 계산이나 로직에 따라 처리된 값
- 게터(getter)를 생성하고 선택적으로 세터(setter) 메서드를 생성하며, 연산을 수행할 코드 포함
- ex) 은행 수수료를 뺀 현재 잔액을 담는 프로퍼티 추가 (getter)
- 부동 소수점 값을 매개변수로 받아서 수수료를 뺀 결과를 프로퍼티에 할당
class BankAccount {
var accountBalance : Float = 0 // 계좌에 남은 잔고
var accountNumber : Int = 0 // 계좌 번호
var fees : Float : 25.00 // 은행 수수료
var balanceLessFees : Float{
get{
return accountBalance - fees
}
set(newBalance){
accountBalance = newBalance - fees
}
}
...
}
// 현재의 잔액에서 수수료를 뺀 값을 얻는 코드와 새로운 값을 설정하는 코드
var balance1 = account1.balaceLessFees
account1.balaceLessFees = 12123.12
지연 저장 프로퍼티
- 프로퍼티 초기화 방법
- 직접 할당
- 초기화 작업에서 할당
- 클로저 사용
// 1. 직접 할당
var myProperty = 10
// 2. 초기화 작업에서 할당
class myClass {
let title : String
init(title : String){
self.title = title
}
}
// 3. 클로저 사용
class myClass {
var myProperty : String = {
var result = resourceIntensiveTask()
result = processData (data : result)
return result
}()
..
}
- 클로저의 경우 초기화 작업이 리소스와 시간이 많이 사용됨
- 해당 프로퍼티가 코드 내에서 실제로 사용되는지와는 상관없이 클래스 인스턴스가 생성될 때마다 초기화 작업이 수행되기 때문
→ 효율적인 방법 : 프로퍼티로 최초 접근할 때만 초기화 작업 (lazy 사용)
class myClass {
lazy var myProperty : String = {
var result = resourceIntensiveTask()
result = processData (data : result)
return result
}()
..
}
self 사용하기
- 현재 클래스 인스턴스에 속한 메서드나 프로퍼티를 가리킬 때 프로퍼티와 메서드 앞에 self를 사용
class MyClass {
var myNumber = 1
func addTen(){
self.myNumber += 10
// myNumber += 10
}
}
→ self는 디폴트이기 때문에 안 써도 됨
단, 프로퍼티나 메서드를 클로저 표현식 내에서 참조할 경우 반드시 사용해야 함
document?.openWithCompletionHandler({(success:Bool) -> Void in
if success {
self.ubiquityURL = resultURL
}
})
- 함수의 매개변수가 클래스 프로퍼티와 동일한 이름일 때도 self 사용
class MyClass{
var myNumber = 10
func addTen(myNumber : Int){
print(myNumber) // 함수의 매개변수 값을 출력
print(self.myNumber) // 클래스 프로퍼티 값을 출력
}
}
프로토콜
- 클래스가 충족해야 하는 최소한의 요구사항을 정의하는 규칙들의 집합
- protocol 키워드 사용
- 클래스가 반드시 포함해야 하는 메서드나 프로퍼티를 정의
- 어떤 클래스가 프로토콜을 채택했으나, 요구사항을 충족하지 않는다면 에러 발생
- 아래 프로토콜을 채택한 클래스는 name 프로퍼티와 buildMessage() 메서드 반드시 포함해야 함
protocol MessageBuilder {
var name : String {get}
func buildMessage() -> String
}
class MyCalss : MessageBuilder {
}
// -> 에러 발생
class MyClass : MessageBuilder{
var name : String
init(name : String){
self.name = name
}
func buildMessage() -> String {
"Hello " + name
}
}
불투명 반환 타입
- 특정 반환 타입(구체화된 타입)을 지정하지 않고, 불투명 반환 유형을 사용하면 지정된 프로토콜을 따르는 모든 타입이 반환될 수 있음
- 프로토콜 앞에 some 키워드를 붙여 선언
- doubleFunc1() 함수가 Equatable 프로토콜을 따르는 모든 타입의 결과가 반환된다고 선언
- Int, String 모두 Equatable 프로토콜을 따른다면 아래와 같이 선언 가능
func doubleFunc1 (value : Int) -> some Equatable {
value * 2
}
func doubleFunc2 (value : String) -> some Equatable {
value + value
}
'Swift' 카테고리의 다른 글
Swift - 7. 구조체 (0) | 2023.12.28 |
---|---|
Swift - 6. 서브 클래싱과 익스텐션 개요 (0) | 2023.12.28 |
Swift - 4. 함수, 메서드, 클로저 개요 (1) | 2023.12.26 |
Swift - 3. 제어 흐름 (0) | 2023.12.26 |
Swift - 2. 연산자와 표현식 (0) | 2023.12.24 |