구조체와 클래스

hoBahk·2021년 7월 12일
0

1. 구조체

구조체의 명명법

구조체를 정의 한다는 것은 새오룬 타입을 생성해주는 것과 마찬가지 이므로 기본 타입 이름(Int, String, Bool 등)처럼 대문자 카멜케이스를 사용하여 이름을 지어준다. 프로퍼티와 메서드는 소문자 카멜케이스를 이용하여 이름은 짓는다.

ex) BasicInformation 구조체 정의

struct BasicInformaion{
    var name: String
    var age: Int
}

ex) BasicInformation 구조체의 인스턴스 생성 및 사용

var parkInfo: BasicInformaion = BasicInformaion(name: "Park", age: 24)
parkInfo.age = 33
parkInfo.name = "bh"

let bhInfo: BasicInformaion = BasicInformaion(name: "bh", age: 33)

//let 으로 선언했기 때문에 바꿀 수 없음
bhInfo.age = 22

2. 클래스

클래스 명명법

클래스를 정의한다는 것은 새로운 타입을 생성해준는 것과 마찬가지로 기본 타입 이름(Int, String, Bool 등)처럼 대문자 카멜케이스를 사용하여 이름을 짓는다. 프로퍼티와 메서드는 소문자 카멜케이스를 사용하여 이름을 지어준다.

ex) Person 클래스 정의

class Person{
    var height: Float = 0.0
    var weight: Float = 0.0
}

클래스를 정의한 후, 인스턴스를 생성하고 초기화하고자 할 때는 기본적인 이니셜라이저를 사용한다.

인스턴스와 객체

흔히 다른 프로그래밍 언어에서는 클래스의 인스턴스를 객체라고 부른다. 물론 스위프트에서도 객체라고 부르는 것이 틀린 것은 아니지만, 스위프트 공식 문서에는 좀 저 한정적인 인스턴스라는 용어를 사용한다.

ex) Person 클래스의 인스턴스 생성 및 사용

// 클래스의 인스턴스는 참조 타입이므로 클래스의 인스턴스를 상수 let으로 선언해도 내부 프로퍼티 값을 변경할 수 있다.
var park: Person = Person()
park.height = 42.1
park.weight = 52.1

let june: Person = Person()
june.height = 33.2
june.weight = 22.1

3. 구조체와 클래스 차이

1) 같은점과 다른점

같은점

  • 값을 지정하기 위해 프로퍼티를 정의할 수 있다.
  • 기능 실행을 위해 메서드를 정의할 수 있다.
  • 서브스크립트 문법을 통해 구조체 또는 클래스가 갖는 값(프로퍼티)에 접근하도록 서브스크립트를 정의할 수 있다.
  • 초기화될 때의 상태를 지정하기 위해 이니셜라이저를 정의할 수 있다.
  • 초기구현과 더불어 새로운 기능 추가를 위해 익스텐션을 통해 확장할 수 있다.
  • 특정 기능을 실행하기 위해 특정 프로토콜을 준수할 수 있다.

다른점

  • 구조체는 상속할 수있다.
  • 타입캐스팅은 클래스의 인스턴스에만 허용된다.
  • 다이니셜라이저는 클래스 인스턴스에만 활용할 수 있다.
  • 참조 횟수 계산은 클래스의 인스턴스에만 적용됩니다.

2) 값 타입과 참조 타입

값 타입과 참조 타입의 가장 큰 차이는 '무엇이 전달되는냐'이다.
어떤 함수의 전달인자로 값 타입의 값을 넘긴다면 전달될 값이 복사 되어 전달 되고,
참조 타입의 값을 넘긴다면 전달될 값이 참조(주소) 되어 전달 된다.

ex) 값 타입과 참조타입의 차이

struct BasicInformation{
    let name: String
    var age: Int
}

var parkInfo: BasicInformation = BasicInformation(name: "park", age: 23)
parkInfo.age = 44

var friendInfo: BasicInformation = parkInfo

print("park's age: \(parkInfo.age)") // 44
print("friend's age: \(friendInfo.age)")// 44

friendInfo.age = 234

print("park's age: \(parkInfo.age)") //44
print("friend's age: \(friendInfo.age)") // 234


class Person{
    var height: Float = 0.0
    var weight: Float = 0.0
}

var park: Person = Person()
var friend: Person = park

print("park's height: \(park.height)")// 0.0
print("friend's height: \(friend.height)")// 0.0

friend.height = 188.8
print("park's height: \(park.height)") // 188.8

print("friend's height: \(friend.height)") //188.8

func changeBasicInfo(_ info: BasicInformation){
    var copiedInfo: BasicInformation = info
    copiedInfo.age = 1
}
func changePeronInfo(_ info: Person){
    info.height = 152.1
}

//changeBasicInfo(_:)로 전달되는 전달인자는 값이 복사되어 전달되기 때문에 parkInfo의 값만 전달된다.
changeBasicInfo(parkInfo)
print("park's age: \(parkInfo.age)")// 44

//changePersonInfo(_:)의 전달인자로 park의 참조가 전달되었기 때문에 park이 참조하는 값들이 변한다.
changePeronInfo(park)
print("park's height: \(park.height)")// 152.1
print("friend's height: \(friend.height)") //152.1

식별 연산자

클래스의 인스턴스 끼리 참조가 같은지 확인 할 때 사용한다.

ex) 식별 연산자의 사용

class Person{
    var height: Float = 0.0
    var weight: Float = 0.0
}

var park: Person = Person()
let friend: Person = park
let anotherFriend: Person = Person()

print(park === friend) //true
print(park === anotherFriend) // false
print(friend !== anotherFriend) // true

3) 구조체과 클래스 선택해서 사용하기

구조체와 클래스는 프로젝트의 성격에 따라, 데이터의 활용도에 따라 구분하여 사용할 수 있다.

애플 가이드라인에서 권장하는 사용 (다음 조건 중 하나 이상에 해당한다면 구조체를 사용하는 것을 권장)

  • 연관된 간단한 값의 집합을 캡슐화하는 것만이 목적일 때
  • 캡슐화한 값을 참조하는 것보다 복사하는 것이 합당할 때
  • 구조체에 저장된 프로퍼티가 값 타입이며 참조하는 것보다 복사하는 것이 합당할 때
  • 다른 타입으로부터 상속받거나 자신을 상속할 필요가 없을 때

구조체로 사용하기에 가장 적합한 예는 좌표계(x, y), 물건의 크기(width, height, depth)가 있다.
하지만 이런 몇가지를 제외하고는 대부분 클래스로 정의하여 사용한다.

profile
호박에 줄 그어서 수박 되는 성장 드라마

0개의 댓글