Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Archives
Today
Total
관리 메뉴

브래의 슬기로운 코딩 생활

7 - 클래스 (class) 본문

2 - 겨울방학/Swift 복습

7 - 클래스 (class)

김브래 2023. 12. 28. 18:43

클래스 vs. 객체 vs. 인스턴스



객체 인스턴스

인스턴스(instance)

실제로 메모리에 할당된 객체(object)
소프트웨어 애플리케이션을 개발하는 데 사용되는, 쉽게 사용할 수 있으며 재사용할 수 있는 기능을 가진 모듈
 
객체의 구성
- 데이터 변수(data variable) or 속성(property)
- 함수 or 메서드(method)

클래스란?

청사진이나 설계도가 건물이 완성된 후의 모습을 나타내고 있는 것처럼 클래스(class)는 객체가 생성되었을 때 어떠한 모습을 보일 것인지를 정의
- int x;
- Student han;  //C++
- 클래스 인스턴스;

Swift 클래스 선언하기

클래스의 기본 구조는 다음과 같다.

class 새로운 클래스 이름 : 부모 클래스 {

  // 프로퍼티

  // 인스턴스 메서드

  // 타입(type) 메서드(클래스 메서드)

}

프로퍼티” 부분은 클래스 내에 포함되는 변수(var)상수(let)를 정의한다.
인스턴스 메서드”는 객체가 호출하는 메서드를 정의한다.
타입 메서드”는 클래스가 호출하는 메서드를 정의한다.

클래스에 저장 프로퍼티(stored property) 추가하기

프로퍼티는
- 초기값이 있거나 init을 이용해서 초기화하거나 옵셔널 변수(상수)로 선언(자동으로 nil로 초기화) 한다.
 
property는 저장 프로퍼티(stored property) 계산 프로퍼티(computed property) 가 있다.

 

class Man{

  var age : Int

  var weight : Double //  age, weight는 stored property

}  //오류 - 초기값 없음


프로퍼티는 초기값이 있거나 옵셔널 변수(상수)로 선언

class Man{

  var age : Int = 1 //stored property는 초기값이 있어야 함

  var weight : Double = 3.5

}

 

class Man{

  var age : Int? //stored property는 초기값이 있어야 함, nil

  var weight : Double!

}


메서드 정의

인스턴스(instance) 메서드, 클래스 또는 타입(class or type)메서드
인스턴스 메서드는 인스턴스에서 동작

 

class Man{

  var age : Int = 1

  var weight : Double = 3.5

  func display(){ //인스턴스 메서드

   print("나이=\(age), 몸무게=\(weight)")

  }

}


인스턴스 만들고 메서드와 프로퍼티 접근

var x : Int
var kim : Man 
- 오류, variable 'kim' used before being initialized
 
var age: Int = 0  
var 변수명: 자료형 = 초기값

 

var 인스턴스명 : 클래스명 = 클래스명()
var 인스턴스명 = 클래스명()
- 클래스명 다음의 괄호는 눈에 보이지 않는 default initializer를 나타냄

 

var Kim : Man = Man()  //:Man은 생략 가능
var Kim = Man()
 
인스턴스.프로퍼티
- kim.age

 

인스턴스.인스턴스메서드
- kim.display()

 

class Man{

  var age : Int = 1

  var weight : Double = 3.5

  func display(){

   print("나이=\(age), 몸무게=\(weight)")

  }

}

var kim : Man = Man()

kim.display() //인스턴스 메서드는 인스턴스가 호출

print(kim.age)


클래스(class or type) 메서드

클래스명.클래스메서드()

 

타입 메서드 또는 클래스 메서드는 클래스 레벨에서 동작

 

타입 메서드는 인스턴스 메서드와 동일한 방법으로 선언하지만 class나 static 키워드를 앞에 붙여서 선언

 

class키워드로 만든 클래스 메서드는 자식 클래스에서 override가능 함

 

class Man{
  var age : Int = 1
  var weight : Double = 3.5
  func display(){
    print("나이=\(age), 몸무게=\(weight)")
  }
  class func cM(){
           print("cM은 클래스 메서드입니다.")
  }
  static func scM(){
            print("scM은 클래스 메서드(static)")
  }
}
var kim : Man = Man()
kim.display() //인스턴스 메서드는 인스턴스가 호출
Man.cM() //클래스 메서드는 클래스가 호출
Man.scM() //클래스 메서드는 클래스가 호출


인스턴스 초기화하기 : init()

클래스, 구조체, 열거형(enum) 인스턴스가 생성되는 시점에서 해야 할 초기화 작업

 

인스턴스가 만들어지면서 자동 호출

 

init 메서드(생성자)


init() { 
}


designated initializer
- 모든 프로퍼티(age, weight)를 다 초기화시키는 생성자

 

init()을 하나라도 직접 만들면 기본적으로 만들어지는 눈에 안보이는 default initializer는 사라짐


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

 

class Man{
  var age : Int = 1
  var weight : Double = 3.5
  func display(){
    print("나이=\(age), 몸무게=\(weight)")
  }
  init(yourAge: Int, yourWeight : Double){
            age = yourAge
            weight = yourWeight
  } //designated initializer
}
//var kim : Man = Man() //오류
//init()을 하나라도 직접 만들면 default initializer는 사라짐
var kim : Man = Man(yourAge:10, yourWeight:20.5) 
kim.display()


인스턴스 만들 때 클래스명 다음 괄호의 의미: init() 호출

class Man{
  var age : Int = 1
  var weight : Double = 3.5
  func display(){
    print("나이=\(age), 몸무게=\(weight)")
  }
  init(yourAge: Int, yourWeight : Double){
           age = yourAge
           weight = yourWeight
   } //designated initializer
}
//var kim : Man = Man() //init()호출 : 오류
var kim : Man = Man(yourAge:10, yourWeight:20.5)
//init(yourAge: Int, yourWeight : Double)호출
kim.display()


self

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

 

아래 소스에서는 매개변수와 구분하기 위해 반드시 self.을 써야함

 

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
  }
}
var kim : Man = Man(age:10, weight:20.5)
kim.display()


stored property와 computed property

computed property(계산 프로퍼티)는 property가 설정되거나 검색되는 시점에서 계산 또는 파생된 값

 

계산 프로퍼티 내에는
- 값을 리턴하는 게터(getter) 메서드
- 값을 대입하는 세터(setter) 메서드

 

class Man{
  var age : Int = 1 // stored property
  var weight : Double = 3.5 // stored property
  var manAge : Int{ //메서드 같지만 computed property임
    get{
    return age-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

 

// manAge는 계산 프로퍼티로 저장 프로퍼티 age의 값에서 1을 뺀 값으로 하겠다는 것임


computed property의 getter

manAge는 계산 프로퍼티로 저장 프로퍼티 age의 값에서 1을 뺀 값으로 하겠다.

 

setter가 없으면 get{ }는 생략할 수 있으며 변경하지 않더라도 var로 선언해야 함


computed property의 setter

setter가 있으면 get{ }는 생략할 수 없음

 

매개변수명은 newValue가 기본

  set(newValue){
      age = newValue + 1
  }


Shorthand Setter Declaration
- setter의 매개변수명이 newValue인 경우에만이렇게 “(newValue)” 생략 가능
  set{
    age = newValue + 1
  }


computed property의 getter와 setter

getter와 setter를 갖는 computed property manAge


method overloading : 생성자 중첩

매개변수의 개수와 자료형이 다른 같은 이름의 함수를 여러 개 정의


매개변수가 다른 두 생성자를 통해 두가지 방법으로 인스턴스를 만들 수 있음


UIImage클래스의 init()함수 overloading

앱에서 이미지 데이터를 관리하는 클래스인 UIImage는 15개의 init()가 overloading되어 있음

 

let myImage: UIImage = UIImage(named: "apple.png")!
var aNewUIImage = UIImage(CGImage: imageRef)

 

1. Loading and Caching Images
init?(named: String, in: Bundle?, compatibleWith: UITraitCollection?)
init?(named: String)
init(imageLiteralResourceName: String)


2. Creating and Initializing Image Objects
init?(contentsOfFile: String)
init?(data: Data)
init?(data: Data, scale: CGFloat)
init(cgImage: CGImage)
init(cgImage: CGImage, scale: CGFloat, orientation: UIImage.Orientation)
init(ciImage: CIImage, scale: CGFloat, orientation: UIImage.Orientation)


Failable Initializers(실패 가능한 생성자: init?)

let myImage: UIImage = UIImage(named: "apple.png")! //느낌표가 왜 있지?
- apple.png파일이 없으면 인스턴스를 만들 수 없고 nil

- nil값도 저장할 수 있으려면 init다음에 “?”를 하며 옵셔널 값이 리턴됨

 

init?(named name: String) // Failable Initializers

- init?로 만든 인스턴스는 옵셔널형으로 만들어져서, 사용하려면 옵셔널을 언래핑해야 해서 위의 예제에서 제일 마지막에 “!”가 있음


failable initializer(실패 가능한 생성자: init? init!)

init다음에 “?” “!” 하며 옵셔널 값이 리턴됨

 

오류 상황에 nil을 리턴하는 조건문이 있음
- return nil

 

init?
init!


failable initializer가 있는 클래스의 인스턴스 생성

- 오류

- error: value of optional type 'Man?' must be unwrapped to a value of type'Man'
- var kim : Man = Man(age:10, weight:20.5)

failable initialize가 nil반환


crash시 발생하는 오류와 .so파일

.so 나 .dylib
shared object
shared library
윈도우의 dll
동적 링크 라이브러리(프로그램 실행 시 필요할 때 연결)


.a
archive library
정적 링크 라이브러리
컴파일 시 포함됨


iOS UIKit component


클래스(class) 상속


superclass와 subclass


부모 클래스와 자식 클래스

상속된 클래스는 부모 클래스의 모든 기능을 상속받으며, 자신만의 기능을 추가


상속받은 클래스들을 하위 클래스(subclass) 또는 자식 클래스(child class)
하위 클래스가 상속받은 클래스는 부모 클래스(parent class) 또는 상위 클래스(super class)

 

단일 상속 (single inheritance)
- Swift에서 하위 클래스는 단 하나의 부모 클래스만 상속받을 수 있음


스위프트 상속

class 자식:부모 {
}
- 부모 클래스는 하나만 가능
- 콜론 다음이 여러 개이면 나머지는 프로토콜

 

class 클래스명:부모명, 프로토콜명{}
- 부모가 있으면 부모 다음에 표기


class 클래스명:부모명, 프로토콜명1,프로토콜명2 {}
class 클래스명:프로토콜명{}
- 부모가 없으면 바로 표기 가능


class 클래스명:프로토콜명1, 프로토콜명2{}
상속은 클래스만 가능

클래스, 구조체(struct), 열거형(enum), extension에 프로토콜을 채택(adopt)할 수 있다.

class 클래스명:부모명, 프로토콜명1,프로토콜명2 {}


상속 : 부모가 가진 것을 물려받아요.


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


override : 부모와 자식에 같은 메서드가 있으면 자식 우선

- 부모와 자식에 display()라는 메서드가 있어서 Student클래스는 display() 메서드가 두 개임
- Student클래스의 인스턴스 lee가 display()를 호출할 때, 자식클래스가 새로 만든 display() 메서드가 우선적으로 호출되려면 func 앞에 override키워드