본문 바로가기

iOS

iOS_week6

클래스 자체가 캡슐화 but 수준이 낮음

구조체는 상속이 불가능 <- 이것만 알아둘 것. 시험범위 아님 다 적지말것

java 같은 언어에서는 class 안의 변수를 필드, 함수를 메소드라 함.

Swift에서는 프로퍼티와 메소드라고 함. 프로퍼티는 웬만하면 stored property.

Swift의 stored property 는 반드시 초기값이 있어야함.

init 메서드로 초기화하는 것이 일반적. 메소드이지만 func를 사용하지 않음. -> '생성자'

class Man{ //캡슐화 수준이 높지 않음
    var age : Int = 1
    var weight : Double = 3.5
    //init(){} 생성하지 않아도 자동으로 생성
    //눈에 보이지 않지만 자동으로 만들어지는 default initializer
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    class func cM(){ //타입 메소드: 클래스 자체가 이용하는 메소드, 객체 생성없이 사용가능
        print("cM은 클래스 메서드입니다.")
    }
    static func scM(){
        print("scM은 클래스 메서드(static)")
    }
}
var kim = Man() // ()는 init()호출하는 것, var kim : Man = Man.init()
kim.display() //인스턴스 메서드는 인스턴스가 호출
print(kim.age)
//Man.display() //Man클래스에서 만들어진 객체가 메서드를 사용가능,Man 자체는 불가 -> class method를 만들면 됨
Man.cM() //클래스 메서드는 클래스가 호출
Man.scM() //클래스 메서드는 클래스가 호출

자식 클래스에서 override 하려면 class 키워드로 클래스 메서드를 생성해야함. (= factory method)

class Man{ //캡슐화 수준이 높지 않음
    var age : Int
    var weight : Double
//    init(){
//        age = 1
//        weight = 3.5
//    }
    init(yourAge: Int, yourWeight : Double){
        age = yourAge
        weight = yourWeight
    } //designated initializer, 초기화가 반드시 필요한 생성자
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }

}
var kim = Man(yourAge:23,yourWeight:71) // ()는 init()호출하는 것, var kim : Man = Man.init()
kim.display() //인스턴스 메서드는 인스턴스가 호출
print(kim.age)

 

self: 클래스 내의 변수와 메서드 가리킴

class Man{ //캡슐화 수준이 높지 않음
    var age : Int
    var weight : Double
//    init(){
//        age = 1
//        weight = 3.5
//    }
    init(age: Int, weight : Double){
        self.age = age //self가 없으면 오류발생, 매개변수는 변경이 불가능한 값. 클래스 내 프로퍼티를 가리킨다는 것을 명시해야함.
        self.weight = weight
    } //designated initializer, 초기화가 반드시 필요한 생성자
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }

}
var kim = Man(age:23,weight:71) // ()는 init()호출하는 것, var kim : Man = Man.init()
kim.display() //인스턴스 메서드는 인스턴스가 호출
print(kim.age)

 

생성자 중첩 (다형성)

-method overloading: 같은 이름의 함수가 여러개 (매개변수의 개수와 자료형이 다름)

class Man{ //캡슐화 수준이 높지 않음
    var age : Int
    var weight : Double
    init(){ //"2" 메서드 오버로딩: 생성자 중첩
        age = 1
        weight = 3.5
    }
    init(age: Int, weight : Double){ //"1"
        self.age = age //self가 없으면 오류발생, 매개변수는 변경이 불가능한 값. 클래스 내 프로퍼티를 가리킨다는 것을 명시해야함.
        self.weight = weight
    } //designated initializer, 초기화가 반드시 필요한 생성자
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var yoo = Man(age:23,weight:71)
yoo.display() //1
var kim = Man()
kim.display() //2

 

failable initializer

class Man{
    var age : Int
    var weight : Double
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double){

            self.age = age
            self.weight = weight
        }

}
var kim : Man = Man(age:-3, weight:20.5)
//정상적인 객체가 아닌 경우에는 안만들어지도록, nil이 나오도록
kim.display()

-> 옵셔널형으로 변경

class Man{
    var age : Int
    var weight : Double
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init?(age: Int, weight : Double){
        if age <= 0 || weight <= 0.0 {
            return nil
        }else{
            self.age = age
            self.weight = weight
        }
    }
}
var kim = Man(age:-3, weight:20.5)! //이경우도 nil인데 강제 언래핑, 크래쉬 발생.
//정상적인 객체가 아닌 경우에는 안만들어지도록, nil이 나오도록.
kim.display() //kim!.display()-> age가 nil 인데 kim을 언래핑, 크래쉬 발생
//두 경우 다 0 밑의 수가 나오지 않으면 오류발생 없음 but, nil인 순간 크래쉬 발생
print(type(of: kim))
class Man{
    var age : Int
    var weight : Double
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init?(age: Int, weight : Double){
        if age <= 0 || weight <= 0.0 {
            return nil
        }else{
            self.age = age
            self.weight = weight
        }
    }
}
//1-1.옵셔널 형으로 선언
var kim : Man? = Man(age:-3, weight:20.5)
//1-2.옵셔널 바인딩
if let kim{ //optional binding
    kim.display()
}else{
    print("nil")
}
//2.인스턴스 생성과 동시에 옵셔널 바인딩
if let yoo = Man(age:23,weight:-0.45){
    yoo.display()
}
guard let kim1 = Man(age: -1, weight: 3) else{ 
//guard let은 특정 블럭 안에서 사용해야함 ex) 함수. 블럭 바깥이라 guard let이 작동안하는것
    print("nil")
    return
}
kim1.display()

 

객체지향언어의 특징 - 상속성

프로토콜은 자바의 인터페이스라고 생각.

부모가 가장 먼저 온다. 부모는 없을수도 있고 있다면 반드시 하나만 상속가능.

여러개가 오면 다 프로토콜을 채택한 것.

상속을 받으면 코드를 따로 작성하지 않아도 부모의 것을 다 사용가능

class Man{
    var age : Int = 1
    var weight : Double = 3.5
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    }
}
class Student : Man{
    
}
let kim : Man = Man(age:10, weight:20.5) //객체 생성시 let을 쓰던 var을 쓰던 상관없음
kim.display()
var lee = Student(age: 5, weight: 10)
lee.display()

 

super : 부모 메서드 호출 시 사용

class Man{
    var age : Int = 1
    var weight : Double = 3.5
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    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){
        self.name = name //자식의 프로퍼티 먼저 초기화
        super.init(age:age, weight:weight) //과제: 이 줄을 안쓰면?
        //부모 생성자의 argument label과 자식의 매개변수를 부모 생성자로 초기화
    }//error:'super.init' isn't called on all paths before returning from initializer
}
var lee : Student = Student(age:20,weight:65.2,name:"홍길동")
lee.displayS()
lee.display()

 

override : 자식 클래스에서 메서드 재정의

class Man{
    var age : Int = 1
    var weight : Double = 3.5
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    }
}
class Student : Man {
    var name : String
    override func display() { //override 키워드 작성
        print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double, name : String){
        self.name = name //자식의 프로퍼티 먼저 초기화
        super.init(age:age, weight:weight) //과제: 이 줄을 안쓰면? 인스턴스의 모든값이 초기값이 
        있어야하기 때문에 반드시 적어야함
    }//error:'super.init' isn't called on all paths before returning from initializer
}
var lee : Student = Student(age:20,weight:65.2,name:"홍길동")
lee.display()

오버라이드할 때는 부모 메서드와 이름, 매개변수, 반환타입이 완전히 일치해야 함

부모와 자식에 display()라는 메서드가 있어서 Student클래스는 display() 메서드가 두 개임

Student클래스의 인스턴스 lee가 display()를 호출할 때, 자식클래스가 새로 만든 display() 메서드가 우선적으로 호출되려면 func 앞에 override키워드 씀

 다음주는 중간고사. 열공!

'iOS' 카테고리의 다른 글

iOS_week10  (0) 2025.11.03
iOS_week9  (0) 2025.10.27
iOS_week5  (0) 2025.09.29
iOS_week4  (0) 2025.09.22
iOS_week_3  (0) 2025.09.15