자바를 공부하는 와중 <클래스와 객체 그리고 인스턴스>라는 단어가 계속 반복되면서 혼란이 오기 시작했습니다. 객체와 인스턴스의 차이가 뭐지? 왜 객체를 어떤 때는 객체라고 부르고 어떤 때는 인스턴스라고 부르지? 클래스 자체가 객체 아닌가? 라는 의문이 들었는데 이 글을 보고 있는 분들도 저와 같은 의문을 갖고 글을 검색해서 들어왔다면
아주 잘 모시겠습니다!! 그럼 시작!
우선 클래스가 '뭔지'는 다들 아실거라고 생각합니다. 예제를 작성할 때 마다 public class DateExample{ } 이렇게 선언하곤 하는데 이때의 public class!를 클래스라고 말합니다. 예제를 실행시키기 위해선 main문을 포함한 class도 있어야 하는데요 이때 클래스를 객체로 선언해줍니다.
public class Date{
public static void main(String[] args) {
Dog dog = new Dog(); //객체 선언!!!!
dog.woofff(); //객체 실행!
}
public class Dog(){} //(중첩)클래스 생성!!!
}
보시면 아래에 Dog 클래스가 생성되어 있고 이 클래스를 main 메소드에서 'dog'란 이름을 가진 Dog 타입 변수로 만들었습니다. 이때 클래스를 dog란 이름을 가진 Dog 타입 변수로 만드는 행위를 객체를 만들었다! 라고 합니다.
이로인해 클래스 자체가 객체 아닌가? 라는 의문에 대한 답은 아니다!라는 것을 알 수 있습니다. 왜냐? 클래스를 main메소드에서 사용하기 위해 하나의 무엇으로 압축해서 활용할 수 있게 만든 것을 '객체'라고 할 수 있습니다.
좀 더 쉽게 생각해 볼까요? Dog max = new Dog(); 저희 옆집에는 개가 사는데 그 개의 이름은 맥스입니다. 아랫집에도 개가 사는데 그 개 이름은 샘이에요 Dog Sam = new Dog();. 산책하다 만난 개 이름은 구글이에요 (구글에 취직하고 싶어서 그렇게 지었대요) Dog google = new Dog();
이제까지 3마리의 개를 만나봤는데 모두 각각 다른 개임에도 불구하고 공통된 개!라는 특성이 있죠. 같은 Dog라는 클래스를 공유하고 있지만 각기 다른 특성을 지닌 객체가(max, Sam, google) 된 것입니다.
이제 좀 더 깊게 들어가 객체가 어떻게 생성되는지를 좀 더 생각해보겠습니다. 다시 Dog dog = new Dog();만을 가지고 생각해봅시다. dog라는 Dog타입 변수가 생성되면 객체는 '힙 메모리'에 생성되고 <dog>변수는 객체의 주소값을 가집니다. 그렇기 때문에 정말 엄밀히 따져보자면 dog 변수 자체는 객체가 아닙니다. dog는 '인스턴스'입니다.
슬슬 .....????이 머리 속에 생겼을 것 같은데요. 저도 두어시간 고민한 문제기에 제가 이해한 범위 내에서 최선을 다해 설명해보도록 하겠습니다.
제가 생각한 인스턴스와 객체를 나누는 기준은 참조와 정합성입니다. 잠깐 인스턴스 = '찐을 참조한 것'라는 것을 기억한 후 예를 봐주세요.
우선 Human me = new Human()이라는 새로운 객체를 생성하겠습니다. 그러면 <찐원본>인 객체는 힙 메모리에 생기고 그와 동시에 <me>는 <찐원본>을 참조하는 주소값을 저장합니다. (C언어의 포인터 개념) 먼저 이때의 <me>는 인스턴스라고 할 수 있습니다. 왜냐? 원본인 객체는 힙 메모리에 있고 <me>는 찐을 참조하고 있기 때문입니다. 그리고 또 <me>는 객체라고 할 수 있습니다! 어? 위에서랑 말이 다르잖아... 라고 하실 것 같은데 인스턴스가 객체를 다이렉트로 가르키면!!! <me>를 Human 클래스의 객체라고 할 수 있고 동시에 인스턴스라고 할 수 있습니다!!(좀 더 읽어주세요)
이제 새로운 객체를 생성해서 인스턴스와 객체가 다름을 보여드리겠습니다! Human을 상속한 Student crazy = new Student()입니다.
(Human) <------(Student)
이때 <crazy>는 (참고로 지금 현재 저의 상태입니다..ㅎㅎ) <찐원본>인 crazy의 찐객체!!!를 힙메모리에 저장하고 그 주소값만 <crazy>에 담아놓은 상태입니다. <crazy>는 찐원본을 !다이렉트!로 가르키기도 하는 인스턴스이죠? 그렇기에 <crazy>를 객체라고 인정함과 동시에 <crazy>는 인스턴스 입니다. 왜냐? 애초에 '참조' 했으니 인스턴스라는건 기본으로 깔고 들어가는거죠 ㅇㅅㅇa
그런데 아까 Student는 Human을 상속받은 클래스라고 했습니다. 이제 Human이라는 클래스를 기준으로 봐볼게요.
Human클래스를 기준으로 <crazy>를 보면 crazy는 Human 객체를 참조합니다. 이건 맞아요. 의심의 여지가 없습니다. 그런데 Human의 찐원본 즉 객체를 다이렉트로 가리킨다고 할 수 있나요? 아닙니다. 즉 정합하지 않습니다. 그렇기에 <crazy>는 Human의 인스턴스이지만 객체는 아닙니다.
현실에 대입해서 설명해보겠습니다. 저는 사람입니다. 완벽히 한치의 어긋남 없이 사람입니다. 이건 누구도 부정할 수 없는 사실입니다. 저라는 인스턴스는 사람이라는 객체를 다이렉트로 가르키고 있기 때문에 사람이라는 클래스의 객체이자 인스턴스라고 할 수 있습니다.
애초에 다이렉트로 가리킨다는 사실 자체가 사람 클래스에 제가 '정합(완벽히 들어맞음)'하다는 것이기에 가짜와 진짜를 구별할 수 없어요. 명품이랑 완전히 똑같은 똑같은 장인이 만들고 똑같은 브랜드에서 나온 짭이 있으면 그걸 가짜라고 할 수 있나요? 그건 진짜죠 (뭔가 철학적으로 가기 시작하는데..ㅎㅎ) 엄밀히 따져보면 구별할 수 있지만 구별이 불필요하죠. 정합하니까요!!
찐을 다이렉트로 가르치는 참조는 그래서 '객체'가 될 수 있습니다. 제가 사람인 것처럼요!
이때의 코드는 Human me = new Human();가 되겠네요
이 글을 작성하면서 플라톤의 이데아라는 개념이 객체와 인스턴스에 완벽히 들어맞는다는 생각을 했습니다. 다시한번 Human은 이데아입니다. 찐원본이자 완벽한 이상향. 현실에는 이데아에 미치지 못하는 불완전한 구현물만이 존재합니다. Human이라는 완벽한 이상향, 사람의 원형에 비하면 <me>는 이곳저곳이 아픈 사람이지만 이데아를 비추는 거울이기도 합니다 (불완전한 거울로 비춘 존재이지만요). 그럼으로 저는 인스턴스이자 객체가 되는 것이죠!!
public class 한강 extends 강(river) {}
한강 han = new 한강();
이라는 코드가 있습니다. <강> 클래스는 강의 원형, 강의 이데아이고 <한강>클래스도 한강의 완벽한 이상향인 한강의 이데아 입니다. 혹시 한강을 금요일 저녁에 가보셨나요?? 정말 엄청나게 시끄럽고 사람도 많고... 낭만이라고는 없는데 이게 한강의 완벽한 이상향이라고 할 수 는 없으니 현실 세계의 한강은 <han>으로 <한강>클래스의 불완전한 구현물일 뿐입니다. (제가 어릴적부터 상상하던 한강은 선선한 날씨와 한적한 강변 산들바람이 부는 완벽한 장소에요!)
하지만 <한강>이라는 이데아를 완벽하게 구현한 현실세계의 장소이니 (비록 불완전하지만) <han>은 <한강>의 객체라고 할 수 있습니다. 위에서 찐과 짭을 설명드렸다시피요!! 그런데 이제 <강>의 관점에서 <han>을 보면 너무나 많은 의문들이 생깁니다.
- <han>은 <강>의 구현체라고 볼 수 있을까요? 아니 애초에 강은 뭔가요? 금요일 저녁에 한강을 가보면 이게 강의 원형이라는 직관적인 느낌이 드나요? 아니 애초에 강의 원형이란 뭘까요? 강의 원형은 뭐길래 한강을 강이라고 하는걸가요? -
금요일 저녁의 한강인 <han>은 너무나 직관적이게도 한강입니다. 대강이나마 완벽한 한강의 이상향이 머리속에서 그려지죠. 비록 추상적인 관념이지만 누구에게나 '완벽한 한강'의 이미지가 생깁니다. 그러나 금요일 저녁의 한강인 <han>을 보고 완벽한 강의 이미지가 머리에 그려지나요? 저는 완벽한 강을 떠올릴라 치면 너무나 많은 의문들이 생깁니다. 이것은 <han>이 강의 직접적인 구현물이 아니기 때문이고 그렇기에 <han>은 강의 인스턴스일 뿐 객체가 될 수 없습니다.
어렵죠....ㅜㅜ 이데아라는 개념을 사용하지 않은 다른 예를 들어보겠습니다.
저는 취준생입니다. 이때 '취준생' 으로 사람을 정의할 수 있나요?
저는 뭐든 될 수 있고 어떤 역할이든 가질 수 있어요. 그런데 그 역할이 저라는 사람을 정의하진 않습니다. <사람>이라는 클래스를 상속받은 <취준생>이라는 클래스를 생성하고 그 클래스로 <개발자취준생>이라는 변수를 만든다면 그 <개발자취준생>은 직관적으로 취준생이며 개발자이고 개발자라는 특성을 제외하더라도 완벽하게 <취준생>과 정합합니다. 그런데 개발자취준생에서 <사람>이 있는지 보려면 개발자의 특성 뿐만 아니라 취준생이라는 특성도 제외해야 합니다. 그러고도 뭔가 더 작업을 해야 사람이라는 특성을 얻을 수 있어요. 사람이 개발자취준생이라는 역할은 가질 수 있지만요!
이때의 코드는
취준생 개발자취준생 = new 취준생();
public class 취준생 extends 사람{};
로 표현할 수 있겠네요
에고... 쓰면서도 헷갈리고 어렵다싶은데 도움이 되었으면 좋겠습니다.
reference - oop - Difference between object and instance - Stack Overflow
'개발 공부 > Java' 카테고리의 다른 글
[자바다] System.in.read() 사용법을 반복문 그리고 엔터와 함께 살펴보기 (0) | 2022.09.27 |
---|---|
[자바다] int string등 각 타입에서 'equals' 와 '==' 구별하는 법 (0) | 2022.09.22 |
[자바다] 윈도우와 맥에서의 캐리지리턴(\r), 라인피드(\n) (0) | 2022.09.15 |
[자바다] printStackTrace(), toString(), getMessage() 의 차이점! (0) | 2022.09.15 |
[자바다] next() 와 nextLine()의 차이점 (0) | 2022.08.22 |
댓글