Dog foot print

[SWIFT] 구조체와 클래스 본문

IOS/Swift

[SWIFT] 구조체와 클래스

개 발자국 2021. 7. 13. 10:03

클래스와 구조체

클래스와 구조체의 공통점

클래스와 구조체는 외형상 비슷한 부분이 많다.

  • 프로퍼티
    • 변수나 상수를 사용하여 값을 저장하는 프로퍼티를 정의할 수 있다.
  • 메소드
    • 함수를 사용하여, 기능을 제공하는 메소드를 정희 할 수 있다.
  • 초기화 블록
    • init 메서드를 두어 객체를 원하는 상태로 설정해주는 초기화 블록을 정의 할 수 있다.
  • 서브스크립트
    • 속성값에 접근할 수 있는 방법을 제공하는 서브스크립트를 정의 할 수 있다.
      • ex : get , set
  • 확장
    • 객체에 함수적 기능을 추가하는 확장(extends) 구문을 사용할 수 있다.
  • 프로토콜
    • 특정 형식의 함수적 표준을 제공하기 위한 프로토콜을 구현할 수 있다.

클래스와 구조체의 차이점

외형상 비슷한 점은 많지만 객체가 구조체보다 더욱 많은 기능 범위를 가지고 있다. 다음은 클래스만 가능한 기능이다.

  • 상속
    • 클래스의 특성을 다른 클래스에게 물려줄 수 있다.
  • 타입 캐스팅
    • 실행 시 컴파일러가 클래스의 인스턴스의 타입을 미리 파악하고 검사할 수 있다.
      • 자식의 클래스가 부모의 클래스인척 할 수 있다.
  • 소멸화 구문
    • 인스턴스가 소멸되기 직전에 처리해야 할 수문을 미리 등록해 놓을 수 있다.
  • 참조에 의한 전달
    • 클래스 인스턴스가 전달 될 떄에는 참조 형식으로 제공되며, 이때 참조가 가능한 개수는 제약이 없다.
      • 인스턴스를 함수의 파라메터 혹은 변수에 할당하게 되면 참조에 의한 전달이 이루어진다.

구조체와 클래스 정의하기

struct [구조체 이름]{
    //구조체 정의 부분
}

class [클래스 이름]{
    //클래스 정의 내용 부분
}

클래스 혹은 구조체의 이름을 정의할 때는 다음과 같은 카멜 케이스방법을 사용한다.

  • 첫 알파벳은 대문자로 시작하며, 나머지 글자는 소문자로 작성한다.
    • Integer, String
      • 단어별로 끊어 첫 글자는 대문자로, 나머지는 소문자로 작성한다.
      • WelcomeMessage, HighOrderFunction
      • 이미 축약된 약어는 모두 대문자로 작성 가능하다.
      • JSON, JSONObject, DTO,
      • 프로퍼티나 메소드를 선언할 때는 소문자로 시작한다.
      • 상수를 정의할 때 처럼 _언더바는 사용하면 안된다.
struct Rect{
    var width : Double = 0.0;
    var height : Double = 0.0;
    var name : String?;

    func desc() -> String {
        return "Rect"
    }
}

Class Line{
    var width : Double = 0.0;
    var height : Double = 0.0;
    var name : String?;

    func desc() -> String {
        return "Line"
    }
}

class혹은 struct내부에 메서드나 프로퍼티를 지정하는 것은 전역 변수에 변수를 적는 것과 동일합니다. 다만, 옵셔널 타입이 아닌 변수나 상수가 존재 할 때, 초기화 이후 까지 값이 없다면 에러를 발생 시키니 주의 해야 합니다.

인스턴스

클래스 혹은 구조체를 선언했다면 이제는 이 내용을 바탕으로 인스턴스를 만들어야지 클래스나 구조체 내부에 있는 메서드나 프로퍼티를 사용 할 수 있습니다. 이처럼 정의를 바탕으로 객체 혹은 구조체로 메모리에 적재하는 것을 인스턴스화 라고 합니다.

let myRect = Rect() //구조체
let myLine = Line() //객체

위의 코드처럼 클래스 명 혹은 구조체명 뒤에 ()를 붙이는 것을 인스턴스 생성 연산자라고 합니다.

TIP : 자바나 자바스크립트 같은 언어에서는 인스턴스화 시키기 위해서 new 키워드를 사용하지만 스위프트에서는 사용하지 않습니다.

위와 같은 인스턴스의 멤버에 접근하는 것은 다음과 같습니다.

print(myRect.width)
print(myRect.height)
print(myLine.width)
print(myLine.height)
print(myRect.desc())
print(myLine.desc())

인스턴스에 .을 붙여 특정 멤버에 접근 하는 연산자를 접근 연산자라고 합니다. 이 연산자 뒤에는 접근하고자 하는 멤버의 이름을 적는다면 해당 멤버가 리턴 됩니다.

초기화

클래스나 구조체의 멤버 변수(프로퍼티)는 인스턴스화 되기 전에 값을 사용자의 임의대로 데이터를 넣는 것을 초기화 initialize라고 합니다.

인스턴스화 이전에 값을 미리 지정하는 방법은 다음과 같이 두가지가 있습니다.

  • 클래스의 구조에서 미리 변수를 할당 하는 방법
  • init 메서드를 정의하여, 객체가 생성될 때, 값을 전달

Note : 주의해야 할 점은 인스턴스화가 되었을 때, 옵셔널로 지정되어 있지 않는 멤버들은 할당이 되어야만 합니다.

인스턴스 연산자를 통하여 미리 값을 전달 해주는 방법은 다음과 같습니다.

class Line{
    var width : Double = 0.0;
    var height : Double = 0.0;
    init(w width : Double, h height : Double){
        self.width = width;
        self.height = height;
    }
}
var myLine = Line(w : 3.0, h : 3.0) //init 메서드를 정의하여, 내부에서 자신이 설정한 로직을 정한 뒤 인스턴스화 . 

Note : Line 클래스 처럼 init 메서드를 정의 할 때, 인스턴스화 되는 객체를 지칭 하기 위해서 self를 사용하였습니다. self 는 인스턴스가 되는 객체 자신을 의미합니다.

Init 메서드를 정의하여 사용하게 되면, 내가 사용하고자 하는 로직을 객체가 초기화 될 때 사용 가능합니다. Line 클래스처럼 멤버변수의 이름을 레이블로 사용하여, 초기화 하는 방법을 memberwise initialize 라고 합니다 .

복사에 의한 전달

var a = 0; 
func add(x : Int){
    a += 1; // 1
    return a;
}
print(a); // 0
var b = a;
b += 1 // 1;
a // 0

struct Line {
    var width = 0.0;
    var height = 0.0;
}
var myLine = Line(); // x : 0.0  ,y : 0.0  ;

func up(line : Line){
    line.y = 1.0;
    return line;
}

print(myLine) // x : 0.0 , y : 0.0

객체를 제외한 거의 모든 자료형은 복사에 의한 전달이 발생합니다. 이는 대부분의 자료형이 구조체로 작성되어 있었기 때문에, 복사에 의한 전달이 발생 하는 것입니다.

Tip : 만약 구조체의 멤버를 변경하고자 할 때는 구조체를 가지고 있는 변수의 타입이 let 타입은 아닌지 확인해야 합니다. 만약 let타입이라면 멤버 변수는 변경되지 않습니다.

struct Line {
    var width = 0.0;
    var height = 0.0;
}
let myLine = Line(); // x : 0.0  ,y : 0.0  ;

myLine.height += 1.0;

참조에 의한 전달

import UIKit;

class Line{
    var width : Double;
    var height : Double;

    init(width : Double, height : Double) {
        self.width = width;
        self.height = height;
    }
}

var myLine = Line(width : 1.0, height : 1.0);

func up(l line : Line){
    line.height += 1.0;
}

up(l: myLine)
print(myLine.height) //2.0

var myLine2 = myLine;
myLine2.height += 1.0;
print(myLine.height); //3

객체는 구조체들과 다르게 참조에 의한 전달이 발생하여, 함수 파라메터로 객체를 전달하거나 변수에 값을 전달 한 뒤, 프로퍼티를 변경하면 다른 변수의 프로퍼티도 동일하게 변경됩니다.

Note : 만약 객체 내부에 정의되어 있는 멤버가 let이라면 변경 할 수 없습니다.

TIP : 객체를 담고 있는 변수가 상수타입이여도 멤버의 변수타입이 var라면 변경 가능합니다.

반응형

'IOS > Swift' 카테고리의 다른 글

[SWIFT] 메서드  (0) 2021.07.13
[SWIFT] 프로퍼티  (0) 2021.07.13
[SWIFT] CLOSURE  (0) 2021.07.09
[Swift] Inout  (0) 2021.07.08
[SWIFT] 함수 시작하기  (0) 2021.07.07
Comments