iOS/Swift이론

Swift) iOS 프로그래밍 : 클래스메서드, init(), 프로퍼티, 메서드 중첩,

Sweetft 2021. 10. 7. 21:17

클래스

 

프로퍼티는 초기값을 주거나, init으로 초기화하거나, 옵셔널 변수(상수)로 선언(자동 nil 초기화)해야한다.

-> stored property(저장 프로퍼티) (자바,C#에서 필드라고 하는 것)

-> 즉 스토어드 프로퍼티는 초기화가 되어있어야 한다.

옵셔널 변수 선언 -> 자료형 다음에 ! 혹은 ? 붙이기 https://yejprogramming.tistory.com/4

 

class Dog{
    var age : Int = 5
    var weight : Double  = 3.5
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
} 
var nala : Dog = Dog()
    // Dog()라는 함수를 호출하는 것은 눈에 보이지 않는 
    // default initializer(= init함수 =생성자!!!)을 호출하는 것
nala.display()
print(nala.weight)

 

클래스 메서드 : 인스턴스가 아닌 클래스가 호출하는 메서드

앞에 class가 붙지만 클래스가 아니고 메서드이다.

class가 아닌 static이 붙는 것도 있음 (둘의 차이는 나중에 공부할 오버라이드와 관계가 있음)

 

class Dog{
    var age : Int = 5
    var weight : Double  = 3.5
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    class func classM(){
        print("Class Method")
    }
    static func staticM(){
        print("Static Method")
    }
} 
var nala : Dog = Dog()
    // Dog()라는 함수를 호출하는 것은 눈에 보이지 않는 
    // default initializer(생성자!!!)을 호출하는 것
nala.display() //인스턴스 메소드
Dog.classM() //클래스 메소드
Dog.staticM() //클래스 메소드(static)

 

init() : 인스턴스 초기화

함수이지만 func로 시작하지 않고 그냥 init() { }을 쓰면 된다.

   - class로 인스턴스 선언할 때 ()에 뭐가 있으면 init 함수 호출한다고 생각!!

인스턴스가 생성되며 자동으로 호출된다.

따로 지정하지 않으면 default initializer

따로 지정한건 designated initializer - stored property의 개수만큼 다 초기화 - 직접 지정하면 default initializer은 사라짐

소멸자 : deinit{} - 인스턴스 사라질 때 자동 호출됨

class Dog{
    var age : Int
    var weight : Double 
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(myAge: Int, myWeight : Double){
        age = myAge
        weight = myWeight
    }
} 
//var nala : Dog = Dog() //오류
var nala : Dog = Dog(myAge:5, myWeight:10.3)
//init()을 직접 만들었기 때문에 default 생성자가 없어져서 초기값을 따로 줘야한다.
nala.display()

 self : 현재 클래스 내 메서드나 프로퍼티를 가르킬 때 메서드나 프로퍼티 앞에 self.을 붙인다.

    (-> C++의 this 처럼)

생략이 가능한 경우도 있고 불가능한 경우도 있다. 불가능한 경우 : 매개변수와 프로퍼티의 이름이 같을 때는 이름 구분하기 위해 프로퍼티에 self.을 써줘야 한다.

class Dog{
    var age : Int
    var weight : Double 
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double){
        self.age = age
         // 프로퍼티와 매개변수의 이름이 둘 다 age로 똑같아서 구분 불가. 프로퍼티에 self. 써야함
        self.weight = weight
         // 프로퍼티와 매개변수의 이름이 둘 다 weight로 똑같아서 구분 불가. 프로퍼티에 self. 써야함
         
    }
} 
//var nala : Dog = Dog() //오류
var nala : Dog = Dog(age:5, weight:10.3)
//inigt()을 직접 만들었기 때문에 default 생성자가 없어져서 초기값을 따로 줘야한다.
nala.display()

 

stored property & computed property

stored property는 일반적인 프로퍼티 - 이 프로퍼티들을 가지고 계산해서 만든 프로퍼티가 computed property

계산 프로퍼티 : getter -값을 리턴, setter -값을 대입

class Dog{
    var intAge : Int //Internation age, stored property
    var weight : Double
    var krAge : Int { //korean age
        get{
        //setter가 없을 때는 get{} 생략 가능하다.
            return intAge+1
        }
    }
    func display(){
        print("나이=\(intAge), 몸무게=\(weight)")
    }
    init(intAge: Int, weight : Double){
        self.intAge = intAge
         // 프로퍼티와 매개변수의 이름이 둘 다 age로 똑같아서 구분 불가. 프로퍼티에 self. 써야함
        self.weight = weight
         // 프로퍼티와 매개변수의 이름이 둘 다 weight로 똑같아서 구분 불가. 프로퍼티에 self. 써야함
         
    }
} 
//var nala : Dog = Dog() //오류
var nala : Dog = Dog(intAge:5, weight:10.3)
nala.display() // 결과 : 나이=5, 몸무게=10.3
var nalaKrAge = nala.krAge
print("한국나이는 \(nalaKrAge)세입니다.") //한국나이는 6세입니다.
var krAge : Int { //korean age
        get{
            return intAge+1
        }
    }
//setter가 없을 때는 밑에 코드처럼get{} 생략 가능하다.

var krAge : Int{
        return intAge+1
    }

-> get이 보이지 않는 computed property

(setter가 이쓸 때는 get{} 생략 불가

 

class Dog{
    var intAge : Int //Internation age, stored property
    var weight : Double
    var krAge : Int { //korean age
        get{
            return intAge+1
        }
        set(momAge){  //set에는 매개변수가 있음
            intAge = momAge-5 //어머니의 나이 보다 5세 적음
        }
    }
    func display(){
        print("나이=\(intAge), 몸무게=\(weight)")
    }
    init(intAge: Int, weight : Double){
        self.intAge = intAge
        self.weight = weight
         
    }
} 
var nala : Dog = Dog(intAge:5, weight:10.3)
nala.display() // 결과:나이=5, 몸무게=10.3
var nalaKrAge = nala.krAge //getter 호출
print("한국나이는 \(nalaKrAge)세입니다.") //결과:한국나이는 6세입니다.
nala.krAge = 7 //setter 호출
print("setter 나이는 \(nala.intAge)세입니다.") //결과:setter 나이는 2세입니다.

위 코드의 setter에서 momAge 자리에 보통 "newValue"라는 값이 들어간다.

또한 newValue 값을 사용하는 경우 set 옆에 (newValue)가 생략 가능하다.

class Dog{
    var intAge : Int //Internation age, stored property
    var weight : Double
    var krAge : Int { //korean age
        get{    return intAge+1    }
        set{     intAge = newValue-5    } //매개변수 자리에 newValue 생략 가능
    }
    func display(){
        print("나이=\(intAge), 몸무게=\(weight)")
    }
    init(intAge: Int, weight : Double){
        self.intAge = intAge
        self.weight = weight
         
    }
} 
var nala : Dog = Dog(intAge:5, weight:10.3)
var nalaKrAge = nala.krAge //getter 호출
print("한국나이는 \(nalaKrAge)세입니다.") //결과:한국나이는 6세입니다.
nala.krAge = 7 //setter 호출
print("setter 나이는 \(nala.intAge)세입니다.") //결과:setter 나이는 2세입니다.

-> 더 정렬된 코드

 

computed property를 잘 써서 코드를 간소하게 만들 수 있지만, 당장은 잘 사용하지 않을 것이다.

(하지만 이해를 위해 알아둬야 함)

 

 

method overloading

   - 같은 이름의 함수를 한 개 이상 정의(매개변수의 개수와 자료형을 다르게 한다)

   - 가장 많이 쓰이는 경우가 생성자(여러 개의 init() 정의)

        - 장점 :사용자의 다양한 요구에 맞춰 인스턴스 생성

 

class Dog{
    var age : Int = 1
    var weight : Double!
    var height : Double!
    func display(){
        print("나이=\(age), 몸무게=\(weight), 키=\(height)")
    }
    init(age: Int, weight: Double, height: Double){
        self.age = age
        self.weight = weight
        self.height = height
    }
    init(age: Int, height: Double){
        self.age = age
        self.height = height
    }
} 

var nala : Dog = Dog(age:5, weight:10.3, height:40)
var daisy : Dog = Dog(age:3, height:60.2)
nala.display() //결과 : 나이=5, 몸무게=Optional(10.3), 키=Optional(40.0)
daisy.display() //결과 : 나이=3, 몸무게=nil, 키=Optional(60.2)

 

failable initializer(실패 가능한 생성자)

let myImage: UIImage = UIImage(named: "apple.jpg")!

   - 마지막에 왜 느낌표가 붙어있을까?   "값이 없을 수도 있다." (오타나 파일이 없는 상황 등을 대비해서)

   - 인스턴스가 옵셔널 형으로 나오기 때문에, 이를 사용하기 위해서는 먼저 옵셔널 언래핑을 해야한다.

   - init 다음에 물음표(?) or 느낌표(!), 오류 상황에 nil 리턴 조건문!!(이 말은 즉, 옵셔널형)

class Dog{
    var age : Int
    var height : Double
    func display(){
        print("나이=\(age), 키=\(height)")
    }
    init?(age: Int, height: Double){
        if age <= 0 {
            return nil
        }
        else {
            self.age = age
        }
        self.height = height
    }
} 

if let nala = Dog(age:5, height:40) {
    nala.display() //결과: 나이=5, 키=40.0
}
if let daisy1 = Dog(age:-1, height:53.2) {
    daisy1.display() //결과X
}

 

참고 : iOS프로그래밍기초(21년-2학기) 한성현 교수님 강의 및 강의 자료 변형, 요약