본문 바로가기
IOS 기초

[IOS 기초] 6주 Swift 문법 5(클래스 failable initializer 상속)파일

by heeaeeeee 2024. 10. 10.

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

 

객체 인스턴스

 

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

 

Swift 클래스 선언하기

 

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

 

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

class Man{
    var age : Int = 0
    var weight : Double = 0.0
}

class Man{
    var age : Int? //= 0
    var weight : Double! //= 0.0
}

 

 

1. 직접 초기화 하는 방법

2. 옵션널  변수로 만들어서(?나 !) 초기값이 자동으로 nll

3.

 

메서드 정의

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

 

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

 

프로그래밍 언어에서 클래스로부터 객체를 만드는 예제

1. C++

#include <iostream>
#include <string>

class Person {
public:
    std::string name;
    int age;

    Person(std::string n, int a) : name(n), age(a) {}

    void introduce() {
        std::cout << "My name is " << name << " and I'm " << age << " years old." << std::endl;
    }
};

int main() {
    Person person("Alice", 30);
    person.introduce();
    return 0;
}

2. Java

public class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void introduce() {
        System.out.println("My name is " + name + " and I'm " + age + " years old.");
    }

    public static void main(String[] args) {
        Person person = new Person("Alice", 30);
        person.introduce();
    }
}

3. C#

using System;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public void Introduce()
    {
        Console.WriteLine($"My name is {Name} and I'm {Age} years old.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Person person = new Person("Alice", 30);
        person.Introduce();
    }
}

4. JavaScript

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    introduce() {
        console.log(`My name is ${this.name} and I'm ${this.age} years old.`);
    }
}

const person = new Person("Alice", 30);
person.introduce();

5. Python

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def introduce(self):
        print(f"My name is {self.name} and I'm {self.age} years old.")

person = Person("Alice", 30)
person.introduce()

6. Swift

class Person {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    func introduce() {
        print("My name is \(name) and I'm \(age) years old.")
    }
}

let person = Person(name: "Alice", age: 30)
person.introduce()

 

클래스(class or type) 메서드

 

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

 

self

 

method overloading : 생성자 중첩

class Man{
  var age : Int = 1
  var weight : Double = 3.5
  init(age: Int, weight : Double){
    self.age = age
    self.weight = weight
  }
  init(age: Int){
       self.age = age
  }
  func display(){
      print("나이=\(age), 몸무게=\(weight)")
  }
}
var kim : Man = Man(age:10, weight:30.5)
var lee : Man = Man(age:3)
lee.display()
kim.display()

 

UIImage클래스의 init()함수 overloading

 

 

클래스(class) 상속

superclass와 subclass

 

부모 클래스와 자식 클래스

프로그래밍 언어의 상속 예제

1. C++

#include <iostream>
#include <string>

class Animal {
protected:
    std::string name;

public:
    Animal(std::string name) : name(name) {}
    virtual void makeSound() {
        std::cout << "The animal makes a sound" << std::endl;
    }
};

class Dog : public Animal {
public:
    Dog(std::string name) : Animal(name) {}
    void makeSound() override {
        std::cout << name << " barks: Woof!" << std::endl;
    }
};

int main() {
    Dog dog("Buddy");
    dog.makeSound();
    return 0;
}

2. Java

class Animal {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }

    public void makeSound() {
        System.out.println("The animal makes a sound");
    }
}

class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " barks: Woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy");
        dog.makeSound();
    }
}

3. C#

using System;

class Animal
{
    protected string name;

    public Animal(string name)
    {
        this.name = name;
    }

    public virtual void MakeSound()
    {
        Console.WriteLine("The animal makes a sound");
    }
}

class Dog : Animal
{
    public Dog(string name) : base(name) {}

    public override void MakeSound()
    {
        Console.WriteLine($"{name} barks: Woof!");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Dog dog = new Dog("Buddy");
        dog.MakeSound();
    }
}

4. JavaScript

class Animal {
    constructor(name) {
        this.name = name;
    }

    makeSound() {
        console.log("The animal makes a sound");
    }
}

class Dog extends Animal {
    constructor(name) {
        super(name);
    }

    makeSound() {
        console.log(`${this.name} barks: Woof!`);
    }
}

const dog = new Dog("Buddy");
dog.makeSound();

5. Python

class Animal:
    def __init__(self, name):
        self.name = name

    def make_sound(self):
        print("The animal makes a sound")

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)

    def make_sound(self):
        print(f"{self.name} barks: Woof!")

dog = Dog("Buddy")
dog.make_sound()

6. Swift

class Animal {
    var name: String

    init(name: String) {
        self.name = name
    }

    func makeSound() {
        print("The animal makes a sound")
    }
}

class Dog: Animal {
    override func makeSound() {
        print("\(name) barks: Woof!")
    }
}

let dog = Dog(name: "Buddy")
dog.makeSound()

 

스위프트 상속

 

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

class Man{
  var age : Int = 1
  var weight : Double = 3.5
  init(age: Int, weight : Double){
    self.age = age
    self.weight = weight
  }
  func display(){
      print("나이=\(age), 몸무게=\(weight)")
  }
}
class Student : Man {
    //비어있지만 Man의 모든 것을 가지고 있음
}
var lee : Student = Student(age: 20, weight: 70.5)
lee.display()
var kim : Man = Man(age:10, weight:30.5)
kim.display()

 

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

class Man{
  var age : Int
  var weight : Double
  init(age: Int, weight : Double){
    self.age = age
    self.weight = weight
  }
  func display(){
      print("나이=\(age), 몸무게=\(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:70.5,name:"홍길동")
lee.displayS()
var kim = Man(age: 10, weight: 30.5)
kim.display()

 

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

// Man 클래스 정의
class Man {
    var age: Int      // 나이를 저장하는 프로퍼티
    var weight: Double // 몸무게를 저장하는 프로퍼티
    
    // 생성자: age와 weight를 매개변수로 받아 초기화
    init(age: Int, weight: Double) {
        self.age = age
        self.weight = weight
    }
    
    // 정보를 출력하는 메서드
    func display() {
        print("나이=\(age), 몸무게=\(weight)")
    }
}

// Man 클래스를 상속받는 Student 클래스 정의
class Student: Man {
    var name: String  // 이름을 저장하는 프로퍼티 (Student 클래스에만 있음)
    
    // display 메서드를 오버라이드하여 Student에 맞게 재정의
    override func display() {
        print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
    }
    
    // Student 클래스의 생성자
    init(age: Int, weight: Double, name: String) {
        self.name = name  // Student 클래스의 프로퍼티 초기화
        super.init(age: age, weight: weight)  // 부모 클래스(Man)의 생성자 호출
    }
}

// Student 인스턴스 생성
var lee: Student = Student(age: 20, weight: 70.5, name: "홍길동")
lee.display()  // Student의 오버라이드된 display 메서드 호출

// Man 인스턴스 생성
var kim = Man(age: 10, weight: 30.5)
kim.display()  // Man의 display 메서드 호출

 

swift에서 failable initializers를 사용하는 이유와 사용 예제

1. 사용 이유

  • 초기화 과정에서 실패 가능성을 명시적으로 처리할 있습니다.
  • 부적절한 입력값이나 필요한 리소스가 없는 경우 안전하게 nil 반환할 있습니다.
  • 옵셔널 타입을 활용하여 초기화 실패를 우아하게 처리할 있습니다.

2. 사용 예제

struct Person {
    let id: String
    let name: String
    
    init?(id: String, name: String) {
        if id.isEmpty || name.isEmpty {
            return nil
        }
        self.id = id
        self.name = name
    }
}

// 사용 예
let validPerson = Person(id: "123", name: "Alice")  // Optional(Person)
let invalidPerson = Person(id: "", name: "Bob")     // nil

 

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

 

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

 

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

class Man{
  var age : Int
  var weight : Double
  func display(){
    print("나이=\(age), 몸무게=\(weight)")
  }
  init?(age: Int, weight : Double){
    if age <= 0 {
      return nil
    }
    else {
      self.age = age
    }
    self.weight = weight
  } // failable initializer
}
var kim : Man = Man(age:10, weight:20.5)
kim.display()
var lee : Man = Man(age:1, weight:3.5)
lee.display()
  • 오류
  • error: value of optional type 'Man?' must be unwrapped to a value of type 'Man'
  • var kim : Man = Man(age:10, weight:20.5)

 

class Man{
  var age : Int
  var weight : Double
  func display(){
    print("나이=\(age), 몸무게=\(weight)")
  }
  init?(age: Int, weight : Double){
    if age <= 0 {
      return nil
    }
    else {
      self.age = age
    }
    self.weight = weight
  } // failable initializer
}
var kim : Man? = Man(age:1, weight:3.5)
//1-1.옵셔널 형으로 선언
if let kim1 = kim { //1-2.옵셔널 바인딩
  kim1.display()
}

//2.인스턴스 생성과 동시에 옵셔널 바인딩
if let kim2 = Man(age:2, weight:5.5) {
kim2.display()
}

//3.인스턴스 생성하면서 바로 강제 언래핑
var kim3 : Man = Man(age:3, weight:7.5)!
kim3.display()

//4.옵셔널 인스턴스를 사용시 강제 언래핑
var kim4 : Man? = Man(age:4, weight:10.5)
kim4!.display()

 

failable initialize가 nil반환

class Man {
    // Man 클래스 정의 시작
    var age : Int     // 나이를 저장할 정수형 변수 선언
    var weight : Double   // 몸무게를 저장할 실수형 변수 선언
    
    func display() {
        // 나이와 몸무게를 출력하는 메서드
        print("나이=\(age), 몸무게=\(weight)")
    }
    
    init?(age: Int, weight : Double) {
        // Failable initializer 정의 시작
        if age <= 0 || weight <= 0.0 {
            // 나이나 몸무게가 0 이하면 초기화 실패
            return nil
        }
        else {
            // 유효한 값이면 프로퍼티 초기화
            self.age = age
            self.weight = weight
        }
    }
}

var kim : Man = Man(age:10, weight:20.5)!
// 유효한 값으로 Man 인스턴스 생성, 강제 언래핑 사용
kim.display()
// kim 인스턴스의 display 메서드 호출

//var lee : Man? = Man(age:0, weight:3.5)
// 주석 처리된 코드: 유효하지 않은 나이로 인스턴스 생성 시도 (nil 반환)

//if let lee {
//    lee.display()
//}
// 주석 처리된 코드: 옵셔널 바인딩을 통한 안전한 접근 시도

if let lee = Man(age:1, weight:0.0) {
    // 유효하지 않은 몸무게로 Man 인스턴스 생성 시도 및 옵셔널 바인딩
    lee.display()
    // 인스턴스 생성에 실패하므로 이 줄은 실행되지 않음
}

 

 

IOS 강의 자료 참고했습니다.

C++, Java, C#, JavaScript, Python, Swift 에서 self나 this 키워드를 사용하는 예제를 작성해줘