티스토리 뷰
INDEX
1. 용어에 대한 이해
2. 클래스와 구조체의 정의 및 초기화
3. 클레스와 구조체의 차이점
4. 객체지향(OOP)의 4대 원칙
5. 마무리
6.출처
이번 포스팅에서는 구조체와 클래스의 기본적인 개념에 대해서, 차이점을 중심으로 설명하고자 한다. Swift에서 구조체와 클래스는 너무나 중요하다. 먼저 이 개념을 공부하는 데 있어서, 기본적인 용어를 정리하고, 구조체와 클래스를 선언하고 초기화해본뒤 둘의 차이점과 공통점에 대해 소개하며 객체지향의 특징을 끝으로 1부를 마무리 한다. 이번 포스팅은 코드보다는 용어와 텍스트 자체에 집중해야한다. 코드도 중요하지만, 밑바탕이 되는 지식이 자리잡혀 있어야 더 정확하게 이해하고 배울 수 있다고 생각한다. 특히 구조체와 클래스의 차이점은 면접에서도 자주 나오는 질문들인 만큼 알아둘 필요가 있다.
1. 용어에 대한 이해
클래스, 구조체의 공부를 위해서는 아래의 용어에 대해 확실히 알고 공부하면 더 편하다
클레스와 구조체 내부의 변수와 상수를 속성(property)라고 하며, 클레스와 구조체 내부에 정의된 함수를 메서드(method)라고 한다.
(다른 언어와 다르게, 스위프트에서는 구조체와 열거형에서도 메서드(함수)의 정의가 가능하다)
클래스와 구조체 둘다, 메모리에 찍어낸 것을 인스턴스(instance)라고 한다
(클레스 구조체는 그저 틀에 불과, 인스턴스가 실제로 메모리에 할당되어 구체적 실체를 갖춘 것)
스위프트에서는 클래스의 instance만을 특별히 객체(object)라고 부른다.(객체 != 인스턴스)
- 클래스의 인스턴스(객체)
- 구조체의 인스턴스
- 열거형의 인스턴스
2. 클래스와 구조체의 정의 및 초기화
2- 1 클래스와 구조체 선언하고 인스턴스 생성하기
//클래스 선언
class Dog{
let name = "도순이"
var weight = 0
func sit() { print("앉았습니다")}
func layDown() { print("누웠습니다.")}
}
//객체(클레스의 인스턴스) 생성
var choco = Dog()
//객체의 속성과 메서드 접근
choco.name //"도순이"
choco.sit() //앉았습니다
//구조체 선언
struct Bird {
var name = "새"
var weight = 0.0
func fly() {
print("날아갑니다.")
}
}
//인스턴스 생성
var aBird = Bird()
//인스턴스의 속성과 메서드 접근
aBird.name //"새"
aBird.fly() //날아갑니다.
2-2 초기화 (init)
초기화란 init키워드로 이루어지며, 인스턴스 생성시 사용하는 특별 메서드로, 객체 생성시 모든 저장 속성(변수)을 초기화 해야 한다.
self 프로퍼티: 인스턴스 내에서 동일한 변수, 상수명 사용시 인스턴스(자기자신)를 더 명확히 지칭하고 싶을때 사용한다.
만약 속성이 옵셔널 타입으로 정의되어 있다면?
-> 반드시 초기화하지 않아도 객체 생성이 가능하다. 이유는 옵셔널타입이기에, 이미 nil로 초기화 되어 있기 때문이다.
class Dog1 {
var name: String
var weight: Int
// ⭐️생성자
init(n: String, w: Int) {
self.name = n //self키워드
self.weight = w //self키워드
}
func sit() {
print("\(self.name)가 앉았습니다.")
}
func layDown() {
print("\(self.name)가 누웠습니다.")
}
}
var dog1 = Dog1(n: "뭉이", w: 12)
dog1.name
dog1.weight
dog1.sit()
dog1.layDown()
class Dog2 {
var name: String?
var weight: Int
// ⭐️생성자
init(weight: Int) {
//self.name = "강아지"
self.weight = weight
}
func sit() {
print("\(name) 앉았습니다.")
}
func layDown() {
print("\(name) 누웠습니다.")
}
}
3. 클레스와 구조체의 공통점과 차이점
구조체와 클래스의 공통점
- 프로퍼티 정의 가능
- 메서드 정의 가능
- 서브스크립트 문법을 정의하여 프로퍼티 접근 가능
- 초기화를 위한 initializier 정의 가능
- 확장이 가능
- 프로토콜 준수 가능
구조체와 클래스의 차이점
구조체(struct)
Value Type(기본타입(Int,String...), 튜플, 열거형, 컬렉션도 Value Type)
값 저장 방법 - 스택(Stack)에 저장
값 전달 방법 - 다른 메모리 공간을 생성해 값을 복사 전달하는 형태
메모리 관리 방식- 스택(Stack)의 공간에 저장하기에, 스택 프레임 종료시, 메모리에서 자동 제거된다
메서드내에서 속성변경은 원칙적으로 불가능하나 mutating키워드로 가능하다.
멤버와이즈 이니셜라이저 (자동)제공
상속 불가능
클래스(class)
Reference Type(클래스와 클로저가 해당)
값 저장 방법 - 힙(Heap)에 값을 저장, 스택(Stack)에 값의 주소를 저장
값 전달 방법 - 주소 전달 형태 (복사 전달 X. 스택에 저장된 주소를 전달하여,
해당 힙을 가르키는 변수는 스택에 저장하고 메모리 주소값이 힙(Heap)을 가르킨다)
메모리 관리 방식 - 힙(Heap)의 공간에 오랫동안 저장하기에, ARC(automatic reference counting)시스템을 통해 메모리 관리한다.
메서드 내에서 속성변경이 원칙적으로 가능하다.
편의 생성자(convenience init())존재
상속 가능
언제 클래스를 사용하고 언제 구조체를 사용해야 할까?
명확한 답이 있는 것은 아니다. 하지만
여러개의 데이터를 묶어 처리하는 상황에서 메모리에 오랫동안 저장할 필요가 없고,
상속기능도 필요없이,
가볍고 빠르게 사용하고 싶다면 구조체,
상속기능이 필요하고, 메모리에 오랫동안 저장하고 관리해야한다면 클레스를 사용해는게 권장된다.
4. 객체지향(OOP)의 4대 원칙
객체지향프로그래밍(OOP):컴퓨터 프로그램을 여러개의 독립 된단위인 객체의 모임으로 파악하고자 하는 시각
객체지향 프로그래밍은 클래스에 하나의 문제 해결을 위한 데이터와 메서드를 모아놓은 방식으로 응집력을 강화한다.
객체 지향의 장점? => 유지보수 + 재사용성, 직관적 코드 분석
4대원칙
1. 캡슐화(Encapsulation) - 모델링, 데이터 캡슐화, 은닉화
연관된 속성(프로퍼티)과 메서드(함수)를 하나로 묶는 개념. 객체를 묶을때는 하나의 목적을 가진 실체라는 관점에서 접근해야 한다. (모델링, 데이터 캡슐화)
public, private과 같은 접근 제어자를 통해 객체 외부의 클래스 내부 데이터 접근통제가 가능하다.(은닉화)
2. 상속(Inheritance) - 재사용, 확장
상위클래스의 속성과 메서드를 하위클래스가 그대로 물려받는 것
3. 추상화(Abstraction) - 모델링
실체들의 공통적인 특성을 뽑아내서 하나의 클래스로 정의하는 것
4. ⭐️다형성 (Polymorphism) - 오버라이딩/오버로딩/Method Dispatch
하나의 객체가 여러 타입으로 저장되고 다양한 방식으로 동작한다(Method Dispatch => 차후에 포스팅할 예정).
오버라이딩(Overriding) : 상위 클래스가 가지고 있는 속성이나 메서드를 하위 클래스가 재정의(override)해서 사용
오버로딩(Overloading) : 메서드의 파라미터(타입, 갯수, Argument Label), 리턴타입을 다르게 선언하여, 같은 이름의 함수여도 각기 다르게 사용하는 것
//오버라이딩 => 재정의. override키워드를 사용한다!
class Human {
func introduce() {
print("나는 사람입니다")
}
}
var me = Human()
me.introduce() //"나는 사람입니다"
class Teacher: Human {
override func introduce() {
print("나는 선생입니다")
}
}
var myTeacher = Teacher()
myTeacher.introduce() //"나는 선생입니다"
//(오버로딩 사용 X. 동일기능의 다른 함수명 정의의 불편함❗️)
func sumInt(_ a: Int, _ b: Int) -> Int {
return a + b
}
func sumDouble(_ a: Double, _ b: Double) -> Double {
return a + b
}
func sumString(_ a: String, _ b: String) -> String {
return a + b
}
//(오버로딩 사용O)
func sum(_ a: Int, _ b: Int) -> Int {
return a + b
}
func sum(_ a: Double, _ b: Double) -> Double {
return a + b
}
func sum(_ a: String, _ b: String) -> String {
return a + b
}
sum(1, 2) // 3
sum(1.5, 2.0)// 3.5
sum("a", "b") // ab
5. 마무리
속성, 메서드, 인스턴스, 객체가 무엇인지,
구조체와 클래스의 선언 및 초기화를 코드로 간단히 할 수 있는지,
self 프로퍼티와 옵셔널 타입의 프로퍼티는 초기화의 관점에서 어떤 장점이 있는지,
클래스와 구조체의 공통점과 차이점은 설명할 수 있는지,
마지막으로 클래스를 통하여, 스위프트가 객체지향 프로그래밍 언어라는 것을 되새길 수 있었다면 PASS
6. 출처
Inflearn Allen님의 강의 노트
Swift 공식문서
야곰님의 스위프트 프로그래밍 3판
개발자 소들님의 블로그 https://babbab2.tistory.com/129 오버로딩vs오버라이딩 예제 코드 참조
'Swift' 카테고리의 다른 글
Swift [Methods, Subscripts, Access Control, Singleton] (0) | 2023.02.17 |
---|---|
Swift [속성(Properties) - Stored/lazy/Computed/Type/Property Obsevers] (0) | 2023.02.15 |
Swift [열거형(Enumerations)] (0) | 2023.02.12 |
Swift [Collection Types] (0) | 2023.02.10 |
Swift [옵셔널(Optionals) 총정리] (0) | 2023.02.09 |