-들어가기에 앞서
객체지향 방식으로 개발을 하다보면, 클래스, 인스턴스화, 생성자, static 등 여러 용어가 나오면서 참조를 한다거나, 인스턴스를 만들어서 값만 변경해준다거나 하는 말을 많이 들어 봤을 것이다. 이러한 말을 이해 하기 위해선 작업 영역에 대한 근본적인 이해가 수반되어야 한다. 이번에는 이를 위한 내용을 다뤄 보고자 한다.
스택(stack) & 힙(heap)
- 스택(stack): 비교적 불안전한 메모리 영역이라 생각하면 좋다. 주로, int, double, float등 값타입의 메모리들이 들어간다. 이전 struct에서 다뤘던 내용에서 박싱과 언박싱에서 스택에 값이 들어가고 참조가 힙에 들어가는 이미지를 참고 하면 좋을 듯하다.
- 힙(heap): 안정적인 메모리영역. 주로 참조 타입이 머무른다. 우리가 흔히 클래스를 말한다.
struct에 관한 이전글)https://note4iffydog.tistory.com/14
개발을 할 때 생성하는 메소드나 변수, 클래스, 인터페이스등 모두 이 둘중 하나의 영역에서 머무르게 되는 것이다. (하나의 집이라고 생각하면 편할 듯하다. 스택 - 공장에서 물건을 생산하느 라인, 힙 - 생산하는 물품의 오리지널 모델들을 모아두는 곳).
private int a = 4; 라고 선언이 된것은 -> 스택, Monster monster = new Monster(); -> 힙(무조건은 아니지만, 일단은 간단히 이해를 위해 힙이라 하겠다. 자세한 것은 뒤에서 다시 다루도록 하겠다.)
복사(값, value) & 참조(ref)
위의 struct글에서 얘기를 하지만, struct는 값타입, class는 참조 타입이라고 본다.
Mage라는 struct 즉, 값타입을 정의 했고, 위와 같이 mage 와 mage2의 hp 값이 다름을 알수 있다.
-왜 그럴까? 바로 스택 영역에서 서로 다른 객체의 주소를 가지고 있기 때문에 hp에 값을 넣어준다해도 mage와 mage2는전혀 다른 영역이기에 다른 값이 들어가게 된다.
Knight는 클래스로 정의하였고, 위의 Mage와는 다른 것을 볼수 있다. -> 참조 타입의 경우 knight의 주소에 knight2가 같이 사용하게 되었기 때문이다. 위의 값타입은 다른 주소를 가지고 있게 되는 것이 다르다.
더 구체적으로 설명하자면 값타입의 경우 위의 Mage타입의 변수가 생성될 때마다, 스택에 전혀 다른 영역이 생성되어 둘이 겹치지 않는 반면, Knight(참조)의 경우 힙에 존재하고 knight변수가 new로 생성이 되어 그 인스턴스가 스택에 들어가게 되는데, 새로운 knight2 변수는 new로 생성 되는게 아니라 힙에서 나와 knight를 할당 되어 버렸기 때문에 겹치게 된다.(즉, 잘살고 있던 knight의 집을 knight2같이 살게 된것이다.)
knight와 knight2를 구분하려면 knight2에 new로 새로이 생성 해주면 된다.
이렇게 매번 생성 해주기 번거롭지 않나?그래서 Clone이라는 함수를 만들어서 생성해보자.
근데, 이렇게 생성 해주는 것 보다, 더 편합 문법이 존재한다. 생성자라는 친구이다.
생성자(constructor)
생성자라는 것은 추상적으로 존재 하는 것을 메모리에 할당해줌으로서 실제 세상에 존재하게 끔 하는것이다. 즉, 스택에 영역 할당해주는 친구들이란 것이다.
public Knight(int a, int b):this() {
}
이런식으로, 빈생성자를 불러 올수도 있다. 패러미터가 존재하는 생성자도 마찬가지.
+) static 으로도 객체를 생성 해줄수도 있다.
Static
static이란 정적이란 뜻이다. 프로그래밍에서 의미하는 바가 무엇인가. 변수나 메소드의 키워드이다. 우리는 메모리에 즉, 스택에 할당한다고 할때 주로 동적(dynamic)할당을 한다. 참조를 예로 들면 우리가 힙 영역에 있는 어떤 것을 new함수를 사용하여 동적으로 할당 한다고 한다. 이와 달리 static도 존재하는데, 쉽게 말해 static이 선언된 곳에 static 메소드나 변수가 종속 된다고 생각하면 쉽다.
-static은 변수나 메소드가 힙영역에 클래스와 같이 존재한다고 생각하면 쉽다. static int a = 0;이라고 한다면, a=0 이라는 것이 포함하고 있는 클래스에 종속되어 존재하는 것이다.
a는 Knight클래스에 종속되어 있는 변수 인데, 거기에 access할려고 하니 instance에 해당되는 친구들은 어디를 가야 할지 모르니 할당이 불가하다.(쉽게 말해, 어디가 주소 인지 몰라 찾아갈수 없다) 대신 knight2나 knight에는 a가 같은 값으로 존재한다. 우리가 클래스의 인스천스끼리 공유 되었으면 하는 값에 사용하면 좋은 방식이다.
예로 인스턴스가 생성 될때 마다, id값을 주고 싶을 때, 각 인스턴스마다 고유의 id값을 가지게 될것이다. 그렇다면, 위에서 얘기한 static으로 인스턴스 생성은 어찌 해야하는가.
다소 불필요해 보일수도 있지만, static은 어차피 클래스에 종속적인 속성이니 static 내부에서 new 해주는 것도 결국 class에서 new하는것과 큰차이는 없다. (static 함수 안에서는 static만 사용해야하는데, 위에서 말했다 싶이 static 함수에서 일반 변수 즉, 인스턴스에 할당이 될 친구들 에게 어디로 가야 할지 알고 사용을 한다는 것인가? obsolete하다.)
'Programming > Dev Architecture' 카테고리의 다른 글
싱글턴 패턴 (제네릭 + thread-safe) (0) | 2022.09.04 |
---|---|
객체지향 프로그래밍(OOP) - 속성 및 원칙 (0) | 2022.06.25 |
객체지향 프로그래밍(OOP) 이란? (0) | 2022.06.25 |
GoF - 싱글턴 패턴 Singleton Pattern (0) | 2021.05.05 |