이번에는 구조체와 클래스에 대해서 알아볼 예정이다.
스위프트에서는 구조체와 클래스가 공존하고 있다.
구조체와 클래스는 프로그래머가 용도에 맞게 사용하고자 할 때에 상당히 용의하게 쓰인다.
구조체와 클래스는 사용법 자체가 거의 비슷하다.
사용법은 비슷하지만 약간의 차이가 있는데 그것은 바로 구조체의 인스턴스는 값 타입이고, 클래스의 인스턴스는 참조타입이다.
인스턴스에 대해서는 추가적으로 이후에 좀더 자세하게 다룰 예정이고, 이번에는 구조체와 클래스에 대한 내용에 대해서
간략히 짚어보고 진행을 할 예정이다.
구조체
구조체의 사용의 문법은 아래와 같다.
struct 구조체 이름 {
프로퍼티와 메소드
}
이렇게 사용을 할 수 있다.
프로터피와 메소드를 합쳐서 구조체와 클래스의 멤버라고 말한다.
추가적으로 변수는 통상적으로 카멜 표기법을 따르지만, 구조체와 클래스는 대문자로 시작하는 파스칼 표기법을 사용하는 것이
암묵적인 개발자의 룰이다. 굳이 이것을 지키지는 않아도 개발하는데에는 아무런 영향이 없다.
name과 age를 가지고 있는 Student struct를 정의했다.
쉽게 말하면 Student가 name, age를 가지고 있는 큰 박스를 정의했다고 생각하면 될 것 같다.
이 구조체를 사용하기 위해서는 인스턴스를 먼저 선언을 해줘야한다.
인스턴스를 선언한다는 것은 구조체와 클래스를 사용하기 위해 메모리에 생성을 해두는 것을 의미한다.
즉, 메모리에 생성된 클래스, 구조체의 실체라고 생각하면 될 것 같다.
kim이라는 인스턴스가 생성된 내용이다. 즉, 쉽게 말하자면 kim이라는 변수에 jaeheung과 32가 들어가 있다는 것을 알 수 있다.
이것을 사용하기 위해서는 일반 C언어의 클래스 사용과 동일하게 진행하면 된다.
이렇게 구조체의 값을 사용하기 위해서는 변수명.프로퍼티 이렇게 사용해주면 된다.
따라서 필자는 kim이라는 구조체 변수에 이름과 나이를 표기하고 싶었기 때문에 kim.name / kim.age로 사용했다.
추가적으로 이제 또 다른 값을 하나 더 넣어보자.
이렇게 추가적으로 선언을 해서 사용하고 싶을 때 마다 사용해주면 된다.
기본적으로 선언을 해주면 어디선가 계속적으로 사용할 수 있기 때문에 굳이 여러개의 변수를 만들어서 조합을 하지 않아도 된다는 장점이 있다.
값을 변경하고 싶을 때에는 일반적인 변수의 값을 바꿔줄 때와 동일하게 사용하면 된다.
기존에 kim.name이 "jaeheung" 이었지만 이부분을 "test"로 변경했다.
이렇게 일반적인 변수의 사용과 동일하게 진행을 하면 된다.
위에서 언급했다 싶이 구조체 안에서는 메소드 정의도 가능하다.
그럼 이전에 진행했던 함수의 내용을 확인하여 구조체 안에 함수를 넣고 진행을 해보도록 하자.
기존에 함수의 내용이 기억이 나지 않는다면 이전글을 참고하면 될 것 같다.
함수 메소드를 구조체에 정의를 하였고, 이름과 나이를 출력해주는 studenPrint라는 함수를 정의했다.
이처럼 구조체 안에 이렇게 다양한 함수 또한 사용이 가능하다.
약간의 집합체라고 생각하면 나름대로 편할 것 같다는 생각이 든다.
그럼 이제 구조체에 선언한 함수 메소드를 사용해보도록 하자.
구조체의 값을 사용할 때와 동일하게 kim.studentPrint() 선언을 통해서 기존에 만들어 둔 것에 대한 활용을 진행하면 된다.
이렇게 사전에 구조체를 사용할 경우에는 예를 들어 일반적인 게임의 몬스터를 다양하게 만들어서 사용을 할 수 있다.
그럼 이제 클래스에 대해서 알아보도록 하자.
클래스
클래스의 사용방법은 구조체의 사용과 상당히 유사하다.
class 클래스 이름 {
프로퍼티와 메소드
}
이렇게 구조체와 동일하게 정의해서 사용하면 된다.
사용을 한번 진행해보도록 하자.
기존에 구조체와 동일하게 사용을 하였지만, initializers 가 없다. 라고 표기가 된다.
기본적으로 클래스는 초기화가 필요한 내용이고, 해당부분에 대해서는 init()이라는 생성자를 클래스 안에 선언을 해주면 된다.
하지만 이부분은 이 다음글에 언급을 할 내용이기 때문에 이번에는 각각의 파라미터를 우선적으로 초기화하고 진행을 할 예정이다.
우선 init은 이후에 다루기로 했기 때문에 이번에는 각각의 파라미터를 초기화 시켜줬다.
이를 통해서 에러가 생기지 않은 내용을 확인할 수 있다.
그럼 이번에는 Company 클래스에 대한 인스턴스를 생성하여 사용을 해보도록 하자.
클래스의 인스턴스 생성법은
클래스의 인스턴스를 생성했다. 필자는 gs25 라는 company 클래스에 대한 인스턴스를 생성했고,
구조체와 다르게 인스턴스를 생성한다는 부분만 알고 있으면 될것 같다.
그럼 이제 gs25라는 클래스 변수에 값을 한번 넣어서 활용해보도록 하자.
구조체 및 일반 변수와 동일하게 값을 이렇게 넣어서 사용해주면 된다.
해당 값이 정상적으로 표기가 되는지 확인을 했고, 이제 구조체에서 진행했던 것처럼 클래스에 메소드를 넣어서 활용을 해보도록 하자.
정상적으로 표기가 되는 듯 싶었지만.. Int 형인 gs25.companytell 이 우선적으로 Int라서 그런거로 해당 내용 부분들은 추가적으로 얘기를 진행할 예정이니 우선적으로 넘어가면 될 것 같다.
companyPrint라는 메소드를 만들어서 구조체와 동일한 사용을 통해서 사용을 진행했다.
그럼 이제 종합적으로 구조체와 클래스에 대한 차이에 대해서 정리를 진행해보자.
구조체와 클래스의 공통점
- 값을 저장할 프로퍼티를 선언할 수 있다.
- 함수적 기능을 선언하는 메서드를 선언할 수 있다.
- 내부 값에 . 을 사용하여 접근할 수 있다.
- 생성자를 사용해 초기 상태를 설정할 수 있다.
- extension을 사용하여 기능을 확장할 수 있다.
- Protocol을 채택하여 기능을 설정할 수 있다.
공통점은 이번에 구조체와 클래스를 사용하면서 확인을 해본 내용을 알 수 있다.
그럼 이제 각각의 고유한 차이에 대해서 확인을 해보도록 하자.
클래스
- 참조 타입으로 ARC로 메모리를 관리
- 상속이 가능하다.
- 타입 캐스팅을 통해 런타임에서 클래스 인스턴스의 타입을 확인할 수 있다.
- deinit을 사용하여 클래스 인스턴스의 메모리 할당을 해제할 수 있다. ( 이후 초기화에서 다룰 예정 )
- 같은 클래스 인스턴스를 여러 개의 변수에 할당한 뒤 값을 변경시키면 모든 변수에 영향을 준다.
구조체
- 값 타입, 구조체 변수를 새로운 변수에 할당할 때마다 새로운 구조체가 할당된다.
- 같은 구조체를 여러 개의 변수에 할당한 뒤 값을 변경시키더라도 다른 변수에 영향을 주지 않는다.
- 구조체는 스택영역에 값이 저장되기 때문에 ARC로 메모리 관리가 안된다.
구조체의 공통점과 차이점에 대해서 우선 간략히 내용을 작성해봤다.
그럼 우선적으로 가장 중요한 클래스는 참조타입이고, 구조체는 값 타입이라는 내용을 다시 한번 코드를 통해서 확인해보도록 하자.
클래스와 구조체 1개씩 선언을 하여 인스턴스를 생성했다. 그리고 숫자를 받아오는 프로퍼티를 1개씩 생성을 하였고, 각각 0으로 초기화를 진행했다.
class1은 TestClass의 인스턴스를 생성을 했고, class2는 class1을 받았고, class3는 class2를 받았다.
이 의미는 TestClass에 대한 구조를 만들었고, 이후에 연결 시켰다는 의미이다.
쉽게 말해서 class1 -> class2 -> class3 이렇게 연결이 된 것으로 이해를 하면 된다.
struct1은 TestStruct의 인스턴스를 생성했고, struct2는 struct2를 받았고, struct3는 struct2를 받았다.
이 의미 또한 위에서 클래스를 설명했다 싶이 이해를 하면 된다.
여기서 서로 이렇게 동일하게 진행을 한 내용은 클래스는 참조 타입이고, 구조체는 값 타입이라는 것을 증명하기 위해서 서로 동일 선상에 놓고 테스트를 진행하는 부분이다.
클래스 테스트에서는 class3.classNumber에 5를 대입했고, 구조체 테스트에서는 struct3.structNumber에 5를 대입했다.
그 결과 클래스에서는 class1과 class2의 값도 5로 바뀐 것을 확인할 수 있다.
이는 위에서 설명했다 싶이 서로 참조타입으로 인하여 연결이 되어있기 때문이다.
그럼 이제 구조체 테스트 내용을 확인해보자. struct3의 structNumber 값을 5로 변경했지만, struct1과 struct2의 structNumber 값이 5로 변하지 않았다. 이렇게 구조체는 값 타입이기 때문에 연결되지 않아서 각각 따로 논다고 생각하면 된다.
그럼 왜 struct2에 struct1을 대입했을까?
이 이유는 그냥 구조체만 가져와서 동일하게 만들어 준다는 의미일 뿐 값을 동일하게 연결시킨다는 내용은 아니다.
즉, struct1 = TestStruct()와 struct2 = struct1 이부분은 간단하게 구조체의 이름을 한번 덜 사용했을 뿐 동일한 구조체를 복사했다고 생각하면 이해가 쉬울 것 같다.
마지막으로 추가 정리를 해본다면 구조체는 값타입이라 동일한 형태의 인스턴스만 참고해서 인스턴스를 만들 뿐 연결하지는 않고, 클래스는 연결한다. 구조체는 연결을 하지 않고 매번 새로운 메모리가 생성되기 때문이다.
따라서 구조체는 ARC 메모리가 관리가 되지 않는다.
이렇게 이해를 하면 되겠다.
'APPLE > Swift 문법' 카테고리의 다른 글
[ 기초 문법 ] 프로퍼티 (0) | 2022.08.11 |
---|---|
[ 기초 문법 ] Init (0) | 2022.08.10 |
[ 기초 문법 ] 옵셔널 (0) | 2022.08.08 |
[기초 문법] 반복문 (0) | 2022.08.05 |
[기초 문법] If문과 Switch 구문 (0) | 2022.08.05 |