SwiftUI

[Swift] 스위프트 클래스 선언방법(프로퍼티, 인스턴스 및 타입메서드 정의,set,get, protocol, self 등)


새로운 스위프트 클래스를 선언할 때 새롭게 만드는 클래스가 어떤 부모 클래스(parent class)에서 파생되었는지를 지정하고 클래스에 포함할 프로퍼티와 메서드를 정의한다. 새로운 클래스에 대한 기본 구문은 다음과 같다.

class 새로운 클래스 이름: 부모 클래스 {  
   // 프로퍼티    
   // 인스턴스 메서드    
   // 타입 메서드
}

선언부의 프로퍼티(property) 부분은 이 클래스 내에 포함될  변수와 상수를 정의하며, 스위프트에서 변수나 상수를 선언할 때와 동일한 방법으로 선언된다.

클래스 내의 캡슐화된 데이터를 프로퍼티(property) 또는 인스턴스 변수(instance variable)라고 한다.

메서드 정의하기

메서드는 타입 메서드(type method)와 인스턴스 메서드(instance method)의 서로 다른 두 가지 형태로 나뉜다.

타입 메서드는 클래스 레벨에서 동작(예를 들어, 클래스의 새로운 인스턴스 생성하기)한다.

반면, 인스턴스 메서드는 클래스의 인스턴스에 대한 작업(예를 들어, 두 개의 프로퍼티 변수에 대한 산술 연산을 하고 결과를 반환하는 것)만 한다.

인스턴스 메서드는 자신이 속하게 될 클래스의 여는 괄호와 닫는 괄호 안에 선언되며, 표준 스위프트 함수 선언 구문을 사용하여 선언된다.

타입 메서드는 인스턴스 메서드와 동일한 방법으로 선언되지만, 선언부 앞에 class 키워드가 붙는다는 점이 다르다.

class BankAccount {   
   //프로퍼티
   var accountBalance: Float = 0    
   var accountNumber: Int = 0   

   //인스턴스 메서드
   func displayBalance() {       
      print("Number (accountNumber)") 
      print("Current balance is (accountBalance)") 
   }    

   //타입메서드
   class func getMaxBalance() -> Float {    
      return 100000.00    
   }
}
 

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

클래스를 가지고 어떤 작업을 하려면 클래스의 인스턴스를 생성해야 한다. 이 과정에서의 첫 번째 단계는 인스턴스에 대한 참조체를 저장할 변수를 선언하는 것이다.
다음과 같이 하여 인스턴스를 생성한다.

var account1: BankAccount = BankAccount()

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

클래스는 인스턴스를 생성하는 시점에 해야 할 초기화 작업이 있을 수 있다. 이 작업은 클래스의 init 메서드 안에 구현된다. BankAccount 클래스에서는 새로운 클래스 인스턴스가 생성될 때 계좌 번호와 잔액을 초기화할 것이다. 이를 위해 init 메서드를 다음과 같이 작성한다.

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 {   
   var accountBalance: Float = 0  
   var accountNumber: Int = 0  

   init(number: Int, balance: Float) {
      accountNumber = number       
      accountBalance = balance   
   }    
   
   deinit {      
      // 필요한 정리 작업을 여기서 수행한다   
   }

   -알라딘 eBook <핵심만 골라 배우는 SwiftUI 기반의 iOS 프로그래밍> (닐 스미스 지음, 황반석 옮김) 중에서

   func displayBalance() {     
      print("Number (accountNumber)") 
      print("Current balance is (accountBalance)")
   }
}

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

우리가 만든 클래스에 있는 인스턴스 메서드를 어떻게 호출하며, 프로퍼티에는 어떻게 접근하는지를 배울 차례다. 이것은 점 표기법(dot notation)을 이용하면 정말로 쉽게 할 수 있다.점 표기법은 클래스 인스턴스 다음에 점을 찍고 그 뒤에 프로퍼티나 메서드 이름을 써서 인스턴스 변수에 접근하거나 인스턴스 메서드를 호출하게 된다.

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

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

타입 메서드 역시 점 표기법을 이용하여 호출된다. 다만, 주의할 점은 클래스 인스턴스가 아니라 클래스에서 호출되어야 한다.

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

스위프트의 클래스 프로퍼티는 저장 프로퍼티(stored property)와 연산 프로퍼티(computed property)로 나뉜다. 저장 프로퍼티는 상수나 변수에 담기는 값이다.

var balanceLessFees: Float {  
   get {       
      return accountBalance - fees  
   }    
   
   set(newBalance) {      
      accountBalance = newBalance - fees 
   }
 
}

지연 저장 프로퍼티

class MyClass {   
   lazy var myProperty: String = { 
      var result = resourceIntensiveTask()  
      result = processData(data: result) 
   return result   
   }()
.
.
}

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

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

스위프트에서 self 사용하기

대부분의 경우는 스위프트에서 self는 선택적으로 사용된다. self를 사용해야 하는 상황은 프로퍼티나 메서드를 클로저 표현식 내에서 참조할 경우다.
예를 들어, 다음의 클로저 표현식에서는 반드시 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)이라고 한다. 프로토콜은 protocol 키워드를 이용하여 선언되며, 클래스가 반드시 포함해야 하는 메서드와 프로퍼티를 정의한다. 어떤 클래스가 프로토콜을 채택했으나 모든 프로토콜의 요구사항을 충족하지 않는다면, 그 클래스가 해당 프로토콜을 따르지 않는다는 에러가 발생하게 된다.

다음의 프로토콜 선언부를 살펴보자. 이 프로토콜을 채택하는 클래스는 이름의 읽을 수 있는 문자열 값에 대한 name이라는 프로퍼티와 매개변수를 받지 않고 문자열 값을 반환하는 buildMessage() 메서드를 반드시 포함해야 한다.

protocol MessageBuilder {  
   var name: String { get }  
   func buildMessage() -> String
}

다음은 MessageBuilder 프로토콜을 채용하는 클래스를 선언한 것이다.

class MyClass: MessageBuilder {  
   var name: String   

   init(name: String) {       
       self.name = name  
   }    
   
   func buildMessage() -> String {
      "Hello " + name   
   }
}
 

불투명 반환 타입(opaque return)

불투명 반환 유형을 사용하면 지정된 프로토콜을 따르는 모든 타입이 반환될 수 있게 한다. 불투명 반환 타입은 프로토콜 이름 앞에 some 키워드를 붙여 선언된다.


//특정 반환 타입(구체화된 타입(concrete type))
func doubleFunc1(value: Int) -> Int {
   return value * 2
}

//불투명 타입 반환 
func doubleFunc1(value: Int) -> some Equatable { 
   value * 2
}

-알라딘 eBook <핵심만 골라 배우는 SwiftUI 기반의 iOS 프로그래밍> (닐 스미스 지음, 황반석 옮김) 중에서

Leave a Reply

error: Content is protected !!