👩🏻🚀
제목에 쓴 것처럼 swift 입문이 끝났다면 헷갈릴 만한 이론을 정리해봤다.
맞다 내가 헷갈려서 쓴거다.
프로그래밍에서 굉장히 중요한 개념인데,
쉽게 말해서 데이터(속성)랑 그 데이터와 관련된 행동(메서드)를 하나로 묶은거야.
각 객체는 클래스, 구조체 등의 타입으로 정의되고,
이 타입을 기반으로 만들어진 구체적인 인스턴스가 객체야.
프로그램의 한 패러다임으로, 객체를 중심으로 프로그램을 구성하는 방법.
이 방식은 현실 세계의 사물이나 개념을 객체로 모델링해서, 프로그램을 더 이해하기 쉽고, 관리하기 쉬운 구조로 만드는 데에 초점을 맞춘다.
이거 진짜 맨날 들어도 까먹음.
이 둘의 차이는 주로 1. 값 타입 2. 참조 타입에 있다.
구조체는 값 타입.
구조체는 인스턴스를 다른 변수나 상수에 할당하거나 함수에 전달할 때, 그 인스턴스의 복사본이 생성된다.
각 인스턴스는 독립적인 값을 갖고 있고, 서로 영향을 주지 않는다.
클래스는 참조 타입.
클래스의 인스턴스를 다른 곳에 할당하거나 전달하면, 인스턴스 자체가 아니라, 그 인스턴스를 가리키는 ‘참조’가 전달된다. 즉, 여러 변수나 상수가 동일한 인스턴스를 공유할 수 있다.
이것 때문에, 한 곳에서 변경하면, 다른 모든 곳에 영향을 준다.
결국에는 구조체는 독립적인 복사본을 만들고 싶을 때 유용하고, 클래스는 여러 곳에서 하나의 인스턴스를 공유하고 싶을 때 적합하다.
나는 사실 코드 짜면 struct가 더 효율적이라고 들었던 것 같은데, 이건 상황마다 다르다.
일반적으로는 Swift 값 타입인 struct를 권장하는데, 특정 상황에서는 참조 타입인 class가 더 적합할 수 있다.
**// Struct 예시**
struct Point {
var x: Int
var y: Int
}
var point1 = Point(x:0, y:0)
var point2 = point1
// point1의 값을 복사하여 point2 생성
point2.x = 5
point2.y = 10
print(point1)
// {x: 0, y: 0}
print(point2)
// {x: 5, y: 10}
// struct 특: point1 값에 영향을 주지 않음
**// Class 예시**
class Person {
var name: String
init(name: String) {
self.name = name
}
}
var person1 = Person(name: "Alice")
var person2 = person1
// person1의 참조를 person2에 할당
person2.name = "Bob"
print(person1.name)
// "Bob"
// person2를 변경하면 person1도 영향을 받음
print(person2.name)
// "Bob"
요렇게 struct는 복사본을 만들고, class는 참조를 공유하는 방식으로 동작한다.
아니다.
클래스에서 ‘init’ 초기화 메서드를 맨날 써야되는건 아니다.
클래스의 인스턴스를 생성할 때 초기 상태를 설정하기 위해서 사용되는 건데,
클래스, 구조체같은 타입을 기반으로 만들어진 구체적인 객체.
예를 들어, ‘사람’이라는 클래스가 있다면, 이 클래스를 바탕으로 만들어진 ‘민수’, ‘수민’ 사람들이 인스턴스임.
각 인스턴스는 해당 타입의 특성을 가지면서도, 각자 고유한 값을 가진다.
👉🏻 **객체(Object)**프로그래밍에서 굉장히 중요한 개념인데,
쉽게 말해서 데이터(속성)랑 그 데이터와 관련된 행동(메서드)를 하나로 묶은거야.
각 객체는 클래스, 구조체 등의 타입으로 정의되고,
이 타입을 기반으로 만들어진 구체적인 인스턴스가 객체야.
클래스, 구조체 등의 타입에 속한 변수, 상수
프로퍼티를 통해 해당 타입의 인스턴스가 가질 수 있는 값이나 특성을 정의한다.
예를 들어, ‘사람’ 클래스에 ‘이름’, ‘나이’와 같은 프로퍼티가 있을 수 있음.
각 사람(인스턴스)는 자신만의 이름과 나이(프로퍼티의 값)을 가지는 것임
class Person {
var name: String // <- 프로퍼티
var age: Int // <- 프로퍼티
init(name: String, age: Int) {
self.name = name
self.age = age
}
}
// 인스턴스
let minsu = Person(name: "민수", age: 25)
let sumin = Person(name: "수민", age: 21)
// 인스턴스의 프로퍼티 사용
print(minsu.name) // 민수
print(sumin.age) // 21
여기서 ‘Person’은 클래스(타입)이고, ‘minsu’, ‘sumin’은 이 클래스의 인스턴스임.
각 인스턴스는 ‘name’, ‘age’라는 프로퍼티를 가지고 있어서, 민수와 수민은 각 다른 이름, 나이를 갖는거임.
간단히 말해서 “규칙의 목록”
iOS에서 프로토콜은 어떤 클래스나 구조체가 가져야 할 메서드나 속성을 정해놓는 거다.
근데 프로토콜 자체는 이런 메서드나 속성이 어떻게 작동하는지 정하지는 않는다. 프로토콜을 쓰는 클래스나 구조체가 정해야 하는 부분이다.
그러니까, 프로토콜은 “TODO 리스트”를 주는 거라고 생각하면 된다.
그리고 이 리스트를 받은 클래스나 구조체는 그 목록에 적힌 일들을 어떻게 할 지 스스로 결정한다.
예를 들어, ‘FullyNamed’ 프로토콜을 만들어보자.
protocol FullyNamed {
var fullName: String { get } // 프로퍼티의 값을 가져옴
}
struct Person: FullyNamed {
var fullName: String
}
let john = Person(fullName: "John Appleseed"
print(john.fullName) // 출력값: "John Appleseed"
이 프로토콜은 ‘fullName’ 이라는 속성을 가져야 한다고 규정해놓은 거다.
그 다음에 ‘Person’이라는 구조체를 만들어서, ‘FullyNamed’ 프로토콜을 채택하고 있다. 이 구조체는 ‘fullName’ 속성을 실제로 구현하고 있다.
그러니깐 프로토콜을 사용하려면
이렇게 하면 다양한 타입이 같은 프로토콜을 따를 수 있고, 코드도 더 유연하고 재사용하기 쉽게 만들 수 있다.