본문 바로가기

iOS/Swift 문법

[Swift문법] 객체지향 프로그래밍 기초 (2)

클래스 인스턴스 선언하기, 초기화하기

이전까지는 클래스에 대한 구조를 정의하였다.

이 클래스를 가지고 어떤 작업을 하려면 인스턴스를 생성해야 한다.

var account1: BankAccount = BankAccount()

이 코드를 실행하면 BankAccount 클래스의 인스턴스가 생성될 것이며, account1이라는 변수를 통해 접근이 가능해진다.

 

 

클래스 인스턴스 초기화하기, 소멸하기

클래스는 인스턴스를 생성하는 시점에 해야 할 초기화 작업이 있을 수 있다. 이 작업은 클래스의 init 메서드 안에 구현된다.

BankAccount클래스에서는 새로운 클래스 인스턴스가 생성될 때 계좌 번호와 잔액을 초기화할 것이다.

class BankAccount {
	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{

	deinit{
    	// 필요한 정리 작업을 여기서 수행
    }
    
}

 

 

메서드 호출하기와 프로퍼티 접근하기

클래스에 있는 인스턴스 메서드를 어떻게 호출되며, 프로퍼티에는 어떻게 접근하는지 알아보자.

이건 점 표현법(dot notation)을 이용하면 정말로 쉽게 할 수 있다.

클래스인스턴스.프로퍼티명
클래스인스턴스.인스턴스메서드()
account1.accountBalance = 6792.2

aaccount1.displayBalance()

 

타입 메서드의 경우는 클래스 인스턴스가 아니라 클래스에서 호출되어야 한다.

예로 보면,

클래스이름.타입메서드()

var maxAllowed = BankAccount.getMaxBalance() // account1. 이 아닌 BankAccount 클래스를 호출

 

 

저장 프로퍼티와 연산 프로퍼티

스위프트의 클래스 프로퍼티는 저장 프로퍼티(stored property)연산 프로퍼티(computed property)로 나뉜다.

저장 프로퍼티는 상수나 변수에 담기는 값이다. BankAccount 예제에서 계좌 이름과 번호 프로퍼티 모두는 저장 프로퍼티다.

BankAccount예제에서 계좌 이름과 번호 프로퍼티는 모두 저장 프로퍼티다.

 

반면, 연산 프로퍼티는 프로퍼티에 값을 설정하거나 가져오는 시점에서 어떤 계산이나 로직에 따라 처리된 값이다.

연산 프로퍼티는 게터(getter)를 생성하고 선택적으로 세터(setter) 메서드를 생성하며, 연산을 수행할 코드가 포함된다.

class BankAccount{
	
    // 기존 변수 및 init이 있다고 가정
    
    let fees: Float = 25.00
    
    var balanceLessFees: Float {
   		get{ // getter
        	return accountBalance - fees
        }
    	
        set(newBalance) { // setter
        	accountBalance = newBalance - fees
        }
    }

}

이렇게 게터와 세터를 선언했다면 연산 프로퍼티에 접근하는 방법은

var balance1 = account1.balanecLessFees // getter

account1.balanceLessFees = 12312.23		// setter

 

 

지연 저장 프로퍼티

프로퍼티를 초기화하는 여러 방법이 있는데, 가장 기본적인 직접 할당 하는 것 외에 클로저를 이용하여 프로퍼티를 초기화라 수도 있다.

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
    }()
}

프로퍼티를 lazy로 선언하면 프로퍼티가 최초로 접근될 때만 초기화된다.

따라서 리소스를 많이 사용하는 작업은 프로퍼티가 필요하게 될 때 프로퍼티 초기화가 끝날 때까지 해당 작업이 지연될 수 있다.

* 지연 프로퍼티는 반드시 변수(var)로 선언되어야 한다.

 

 

스위프트에서 self 사용하기

객체지향 프로그래밍 언어에 익숙한 개발자라면 현재의 클래스 인스턴스에 속한 메서드나 프로퍼티를 가리킬 때 프로퍼티와 메서드 앞에 self를 붙이는 습관이 있을 것이다.

스위프트 프로그래밍 언어 역시 self 프로퍼티 타입을 제공한다.

class MyClass{
	var myNumber = 1
    
    func addTen(){
    	self.myNumber += 10
    }

}

이 코드에서 self는 MyClass 클래스 인스턴스에 속한 myNumber라는 이름의 프로퍼티를 참조한다는 것을 컴파일러에게 알려준다.

하지만, 대부분의 경우 스위프트로 프로그래밍할 때는 self를 사용할 필요가 없다.

self는 프로퍼티와 메서드에 대한 참조를 디폴트로 간주하기 때문이다.

 

애플이 출간한 <The Swift Programming Language>에 따르면,

'사실상 여러분의 코드에서 self를 그렇게 자주 쓸 필요가 없다'고 적혀 있다.

따라서 위의 코드도 self를 생략하여 쓸 수도 있다.

 

하지만 self를 사용해야 하는 상황은 생각보다 자주 있기도 하다..

프로퍼티나 메서드를 클로저 표현식 내에서 참조할 경우다.

예를 들어

document?.openWithCompletionHandler({(success: Bool) -> Void in
	if success {
    	self.ubiquityURL = resultURL  // self 필수!
    }
})

 

또한, 함수의 매개변수가 클래스 프로퍼티와 동일한 이름을 가질 경우와 같이 코드의 모호성을 해결하기 위하여 self를 사용해야 한다.

예를들어

class MyClass{
	
    var myNumber = 10 // 클래스 프로퍼티
    
    
    func addTen(myNumber: Int){
    	print(myNumber)			// 매개변수 출력
        print(self.myNumber)	// 클래스 프로퍼티 출력
    }
}

 

 

 

 

 

 

출처 : 핵심만 골라 배우는 SwiftUI 기반의 iOS 프로그래밍

책을 보면서 내용을 정리했습니다.. 혹시 틀린 내용이 있다면 댓글로 언제나 말씀해주세요!!!☺️