객체지향 용어 비교
스위프트 클래스 선언하기
class 새로운 클래스 이름: 부모 클래스 {
// 속성(프로퍼티)
// 인스턴스 메서드
// 타입(type) 메서드(클래스 메서드)
}
- "속성" 부분은 클래스 내에 포함되는 변수(var)와 상수(let)를 정의 한다.
- "인스턴스 메서드"는 객체가 호출하는 메소드를 정의한다.
- "타입 메서드" 는 클래스가 호출하는 메서드를 정의한다.
인스턴스 선언하고 초기화하기, 해제하기
- 위의 클래스를 가지고 어떠한 일을 하기 위해서는 클래스의 인스턴스를 만드어야 한다.
- 가장 먼저 할 일은 인스턴스가 만들어졌을 때 이 인스턴스의 참조체를 저장할 변수를 선언하는 것
· var 인스턴스명: 클래스명 = 클래스명()
· var 변수명: 자료형 = 초깃값
- 클래스가 생성되는 시점에서 해야할 초기화작업이 있을 경우
→클래스 내에 있는 init 메서드에 위치 시킨다.
ex)
class BankAccount {
var accountBalance: Float = 0
var accountNumber: Int = 0
init(number: Int, balance: Float)
{
accountBalance = balance
accountNumber = number
}
func displayBalance() //인스턴스 메서드
{
print("Number \(accountNumber)")
print("Current balance is \(accountBalance)")
}
}
var account1 = BankAccount(number: 12312312, balance: 400.54)
// init 메서드 있고 나서는 인스턴스를 생성할 때 초기화 값을 제공해야 함
- 그와는 반대로, 클래스 인스턴스가 스위프트 런타임 시스템에 의해 해제되기 전에 수행되어야 할 정리 작업은
클래스의 해제자를 구현하여 수행하게 된다
deinit { //C++의 소멸자
// 필요한 정리 작업을 수행하는 곳
}
메서드 호출하기와 속성 접근하기
- 도트 표기법은 인스턴스 다음에 점(도트, dot)을, 그리고 그 다음에 속성 또는 메서드의 이름을 지정하여 변수나 메서드를 호출한다.
classInstance.propertyName
classInstance.instanceMethod()
- 타입 메서드는 클래 인스턴스가 아닌 클래스 타입으로 호출되어야 한다.
ClassName.typeMethod()
저장된 속성과 계산된 속성
property
- 저장된 속성(stored property)
- 계산된 속성(calculated property) : 속성이 설정되거나 검색되는 시점에서 계산 또는 파생된 값
if) 현재 잔고에 은행 수수료를 뺀 값을 담는 속성 추가
class BankAccount {
var accountBalance: Float = 0 //저장된 속성
var accountNumber: Int = 0
let fees: Float = 25.00 //추가된 저장된 속성
var balanceLessFees: Float { //계산된 속성
get { //이 줄은 생략 가능
return accountBalance – fees
} //이 줄은 생략 가능
}
init(number: Int, balance: Float)
{
accountNumber = number
... ..
}
- setter가 없으면 get{ }는 생략할 수 있으며 변경 하지 않더라도 var로 선언해야 함
- 세터도 동일한 방식으로 선언하면 입력된 잔고 값에서 수수료를 뺀 값을 설정하게 된다.
var balanceLessFees: Float {
get {
return accountBalance - fees
}
set(newBalance) {
accountBalance = newBalance - fees
}
}
스위프트 self 이용하기
- 객체지향 프로그래밍 언어에 익숙한 프로그래머는 현재 클래스 인스턴스에 속한 메서드나 속성을 가리킬 때 메서드나 속성 앞에 self를 붙이는 습관
- 스위프트 프로그래밍 언어 역시 그렇게 사용하는 self 속성 타입을 제공 하지만 대부분의 경우는 self를 사용할 필요가 없다.
왜냐하면 self가 속성과 메서드에 대한 디폴트 참조체라고 가정하기 때문이다.
self를 사용해야 하는 상황은
1. property나 메서드를 클로저(closure) 표현식 내에서 참조할 경우
document?.openWithCompletionHandler({(success: Bool) -> Void in
if success {
self.ubiquityURL = resultURL //클로저 표현식 내
}
})
2. 함수의 매개변수가 클래스 속성과 동일한 이름을 가질 경우
class MyClass {
var myNumber = 10 // property
func addTen(myNumber: Int) {
print(myNumber) // 함수의 매개변수 값을 출력한다
print(self.myNumber) // property 값을 출력한다. 10
}
}
클래스 이해를 위한 추가 소스들
class Man{
var age : Int = 1
var weight : Double = 3.5
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
class func cM(){
print("cM is a class method")
}
}
var kim : Man = Man()
kim.display()
Man.cM()
class Man{
var age : Int = 1
var weight : Double = 3.5
var manAge : Int{
get{
return age-1
}
set(USAAge){
age = USAAge + 1
}
}
func display(){
print("나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double){
self.age = age
self.weight = weight
}
}
var kim : Man = Man(age:10, weight:20.5)
kim.display()
print("나이가 만으로 \(kim.manAge)")
print("나이 \(kim.age)")
kim.manAge = 3
print("만 나이를 3살로 바꾸면 나이는 \(kim.age)")
class Man{
var age : Int = 1
var weight : Double = 3.5
init(age: Int, weight : Double){
self.age = age
self.weight = weight
}
}
class Student: Man{
var name : String = "김소프"
func displayS()
{
print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
}
init(age: Int, weight : Double, name : String)
{
super.init(age:age, weight:weight)
self.name = name
}
}
var lee : Student = Student(age:20, weight : 65.2, name : "홍길동")
lee.displayS()
스위프트 상속
class BankAccount{
var accountBalance: Float //현재 잔고
var accountNumber: Int //계좌 번호
init (number: Int, balance: Float){
accountNumber = number
accountBalance = balance
}
func displayBalance(){
print("Number \(accountNumber)")
print("Balance \(accountBalance)")
}
}
class SavingsAccount: BankAccount { //class 자식:부모
//부모인 BankAccount 클래스의 모든 메서드와 속성을 상속받음
var interestRate: Float = 0.1 //이자율
init(number: Int, balance: Float, rate: Float) {
interestRate = rate //자신의 property 초기화
super.init(number: number, balance: balance) //부모의 init호출하여 부모의 property 초기화
}
func calculateInterest() -> Float {
return interestRate * accountBalance
}
override func displayBalance() {
super.displayBalance() //부모의 메서드 호출
print("Prevailing interest rate is \(interestRate)")
}
}
var savings1: SavingsAccount = SavingsAccount(number: 12311, balance: 600.00, rate: 0.07)
print(savings1.calculateInterest())
savings1.displayBalance()
- 계좌 번호와 현재 잔고를 담기위한 BankAccount에서 저축 계좌로 사용할 클래스가 필요하다면 새로운 클래스를 만드는 것보다 하위 클래스로 새로운 클래스를 만드는 것이 좋다
- accountBalance는 부모 클래스 BankAccount에 있는 프로퍼티
ex)
func calculateInterest() -> Float {
return interestRate * accountBalance
}
- 메서드 오버라이딩을 할 때 반드시 따라야 할 두 가지 규칙
오버라이딩 메서드는 오버라이딩되는 부모 클래스 메서드의 인자 개수와 타입이 정확하게 일치해야 한다.
부모 클래스 메서드가 반환하는 타입과 일치해야 한다.
ex)
override func displayBalance() {
super.displayBalance() //부모의 메서드 호출
print("Prevailing interest rate is \(interestRate)")
}
- 하위 클래스에서 상위 클래스의 오버라이드된 메서드를 호출하여 중복을 없앤다
ex)
override func displayBalance() {
super.displayBalance() //부모의 메서드 호출
print("Prevailing interest rate is \(interestRate)")
}
스위프트 클래스 인스텐션
- 스위프트 클래스에 새로운 기능을 추가하는 또 다른 방법은 익스텐션(Extension)을 이용하는 것이다.
- 익스텐션은 하위 클래스를 생성하거나 참조하지 않고 기존 클래스에 메서드, 초기자, 그리고 계산된 속성과
서브스크립트 등의 기능을 추가하기 위하여 사용
- 스위프트 언어의 built-in 클래스와 iOS 프레임워크에 내장된 클래스에 기능을 추가할 때, 익스텐션을 이용하면 매우 효과적임
ex)
- 표준 Double 클래스에 두 배와 세 배의 값을 반환하는 속성을 추가
extension Double {
var squared: Double {
return self * self
}
var cubed: Double {
return self * self * self
}
}
print(3.0.squared)
print(3.0.cubed)
let myValue: Double = 3.0
print(myValue.squared) //9.0
- myValue 상수를 선언할 때 Double형이 되도록 선언하고 익스텐션 속성을 사용했는데 이 속성은 하위 클래스를 사용하는 것이 아니라 익스텐션으로 추가된 것이므로, 우리는 Double 값에서 직접 이 속성에 접근할 수 있다.
print(3.0.squared)
print(3.0.cubed)
- 익스텐션은 하위 클래스를 사용하지 않고 클래스에 기능을 확장할 수 있는 빠르고 편리한 방식을 제공한다
- 단, 익스텐션을 이용해서는 클래스에 있는 기존의 기능을 오버라이드할 수 없으며 익스텐션은 stored property를 포함할 수도 없다.
'iOS 프로그래밍 > 문법' 카테고리의 다른 글
[swift] 문법정리6 (옵셔널 체이닝) (0) | 2020.07.31 |
---|---|
[swift] 문법정리5 (배열, 딕셔너리,클래스와 구조체 열거형 비교) (0) | 2020.07.31 |
[swift] 문법정리3 ( 함수와 메서드, 클로저) (0) | 2020.07.30 |
[swift] 문법 정리2 (0) | 2020.07.30 |
[swift] 문법 정리1 (0) | 2020.07.30 |