iOS 프로그래밍기초 수업 7주차

도연·2022년 10월 17일
0
post-thumbnail

클래스(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() 

// 나이=1, 몸무게=3.5
// cM은 클래스 메서드입니다.
// scM은 클래스 메서드(static)

Initialization

https://docs.swift.org/swift-book/LanguageGuide/Initialization.html

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

  • 클래스, 구조체, 열거형(enum) 인스턴스가 생성되는 시점에서 해야 할 초기화 작업
  • 인스턴스가 만들어지면서 자동 호출됨
  • designated initializer
    • 모든 프로퍼티(age, weight)를 다 초기화시키는 생성자
  • init()을 하나라도 직접 만들면 기본적으로 만들어지는 눈에 안보이는 default initializer는 사라짐
  • 소멸자
    • 인스턴스가 사라질 때 자동 호출
    • deinit{}
class Man{
  var age : Int = 1      // 초기값 1과 3.5는 생략 가능
  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
  init(yourAge: Int, yourWeight : Double){
    age = yourAge  //self.age = yourAge
    weight = yourWeight
  }
}
  • 아래의 소스에서는 매개변수와 구분하기 위해 반드시 써야함
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 메서드

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

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)

// 실행결과
나이=10, 몸무게=20.5
9

computed property의 getter

  • manAge는 계산 프로퍼티로 저장 프로퍼티 age의 값에서 1을 뺀 값으로 하겠다
  • setter가 없으면 get{ }는 생략할 수 있으며 변경하지 않더라도 var로 선언해야 함
class Man{
  var age : Int = 1
  var weight : Double = 3.5
  var manAge : Int{  //메서드 같지만 계산 프로퍼티임
   //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)

// 실행결과
나이=10, 몸무게=20.5
9

computed property의 setter

  • setter가 있으면 get{ }는 생략할 수 없음
  • 매개변수명은 newValue가 기본

set(newValue){
age = newValue + 1
}

  • Shorthand Setter Declaration
    • setter의 매개변수명이 newValue인 경우에만 이렇게 “(newValue)” 생략 가능

set{
age = newValue + 1
}

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)  //9, getter호출
print(kim.age)     //10
kim.manAge = 3     //setter호출
print(kim.age)      //4  

// 실행결과
나이=10, 몸무게=20.5
9
10
4

computed property의 getter와 setter

  • getter와 setter를 갖는 computed property manAge
class Man{
  var age : Int = 1
  var weight : Double = 3.5
  var manAge : Int{
    get{  return age-1  }
    set{  age = newValue + 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)  //9, getter호출
print(kim.age)     //10
kim.manAge = 3     //setter호출 
print(kim.age)      //4

// 실행결과
나이=10, 몸무게=20.5
9
10
4

method overloading : 생성자 중첩

  • 매개변수의 개수와 자료형이 다른 같은 이름의 함수를 여러 개 정의
  • 매개변수가 다른 두 생성자를 통해 두가지 방법으로 인스턴스를 만들 수 있음
class Man{
  var age : Int = 1
  var weight : Double = 3.5
  func display(){
    print("나이=\(age), 몸무게=\(weight)")
  }
  init(age: Int, weight : Double){  //1
    self.age = age
    self.weight = weight
  }
  init(age: Int){  //2
       self.age = age
  }
}
var kim : Man = Man(age:10, weight:20.5)  //1 
var kim1 : Man = Man(age:10) //2
//var kim2 : Man = Man() 
//init가 없다면 인스턴스 만드는 방법
kim.display()
kim1.display()

// 실행결과
나이=10, 몸무게=20.5
나이=10, 몸무게=3.5

UIImage클래스의 init()함수 overloading

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가 있는 클래스의 인스턴스 생성

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

failable initialize가 nil반환

과제 : 나이와 몸무게가 음수이면 nil을 반환하는 failable initialize 구현

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

  • .so 나 .dylib

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

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

iOS UIKit component

iOS UIKit class hierarchy에서 init() 찾아 간단 사용 예

클래스(class) 상속

Inheritance

https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html

superclass와 subclass

부모 클래스와 자식 클래스

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

  • 상속받은 클래스들을 하위 클래스(subclass) 또는 자식 클래스(child class)

  • 하위 클래스가 상속받은 클래스는 부모 클래스(parent class) 또는 상위 클래스(super class)

스위프트 상속

  • class 자식:부모 {
    }
    • 부모 클래스는 하나만 가능
    • 콜론 다음이 여러 개이면 나머지는 프로토콜
  • class 클래스명:부모명, 프로토콜명{}
    • 부모가 있으면 부모 다음에 표기
  • class 클래스명:부모명, 프로토콜명1,프로토콜명2 {}
  • class 클래스명:프로토콜명{}
    • 부모가 없으면 바로 표기 가능
  • 상속은 클래스만 가능

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

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 {
  //비어있지만 Man의 모든 것을 가지고 있음
}

var kim : Man = Man(age:10, weight:20.5)  
kim.display()
var lee : Student = Student(age:20,weight:65.2)  
lee.display()
print(lee.age)

// 실행결과
나이=10, 몸무게=20.5
나이=20, 몸무게=65.2
20

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

class Man{
  var age : Int 
  var weight : Double 
  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) // 이 줄을 안쓰면??
  }  //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()

// 실행결과
이름=홍길동, 나이=20, 몸무게=65.2
나이=20, 몸무게=65.2

overriding 이란?

https://en.wikipedia.org/wiki/Method_overriding

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

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

  • Student클래스의 인스턴스 lee가 display()를 호출할 때, 자식클래스가 새로 만든 display() 메서드가 우선적으로 호출되려면 func 앞에 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() {
    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.display()

// 실행결과
이름=홍길동, 나이=20, 몸무게=65.2
  출처:iOS프로그래밍기초 (22-2학기)한성현교수님 강의 내용 변형 및 요약 7주차
profile
초보개발자..ㅠ

0개의 댓글