[JAVA] 객체지향 1 - 클래스와 객체 등

노을지는·2022년 4월 23일
0

JAVA

목록 보기
1/7

들어가며

나는 교재를 보거나 강의를 들으면서 알아둬야 할 것, 헷갈렸던 것 등을 필기해두는데, 그것을 토대로 포스팅해보도록 하겠다. 어디서나 볼 수 있는 내용을 모두 기입하기보다는, 같은 입문자의 시선에서 이해가 잘 안됐던 것들을 내가 나름대로 이해한 방법이나 경험들로 알려주는 것이 좀 더 도움이 되지 않을까 생각한다.

클래스와 객체

클래스와 객체는 흔히 붕어빵 틀과 붕어빵의 관계로 많이 비유되곤 하지만 솔직히 잘 와닿지는 않는다...

그래서 내 나름대로 이해한 것을 설명해보자면, 클래스를 통해서 여러 특성(property)과 기능(function)을 설정하고, 그러한 것들을 객체라는 것에 압축시켜 그로 하여금 대표성을 띄게 하는 것이다. 그러면 객체를 통해서 클래스에 담긴 내용들을 가져다 쓸 수 있게 되는 것이다.

C의 구조체(struct)라는 개념과 흡사하다. 뭐가 먼저 등장했는지는 모르겠지만...

인스턴스의 생성

클래스로부터 만들어진 객체를 인스턴스(instance)라고 하여 거의 동일어지만 인스턴스는 메모리 위에 올라간 객체를 뜻한다고 보면 된다.

Item doranSword = new Item(); 

Item이란 클래스에서 doranSword라는 참조변수를 우선 선언한다. new 연산자를 통해 Item 클래스의 객체가 생성되고, 메모리의 heap 영역에 인스턴스가 생성된다. 생성자 Item()가 호출되고, 객체의 주소는 참조변수에 저장되어 참조변수를 통해 인스턴스를 접근할 수 있게 해준다.

JAVA에 포인터가 없는 이유

C에는 포인터라는 개념이 있는데, 메모리의 주소값을 저장하는 변수이다. 엄청나게 중요하지만 C를 처음 배우는 사람들에겐 C의 수문장으로 활약할 만큼 어렵게 느껴진다. C에서는 바로 이 포인터를 사용하여 직접 주소에 접근할 수 있어서 micro한 컨트롤을 할 수 있지만, JAVA에서는 프로그램의 안정성과 Garbage Collector(GC)라는 것이 있어서 주소에 참조만 하여 사용한다.

주소를 잘못 건드리면 심각한 오류가 발생할 수 있고, 메모리를 알아서 정리해주는 GC때문에 객체의 주소가 계속 바뀌게 되어 그냥 참조만 하여 사용하도록 한 것이다.

나도 포인터에서 한 번 막혀봐서 JAVA에 포인터가 없는 것이 그나마 다행이라고 생각은 하는데 포인터 말고도 머리 아프게 하는 개념들은 많아서 그렇게 좋아할 일도 아니더라...

변수

간단히 생각해서 static이 붙으면 클래스 변수, 안 붙으면 인스턴스 변수, 메소드 안에 있으면 지역 변수(local variable)다. 헷갈렸는데 그냥 저렇게 퉁쳐버리니까 구별이 좀 되더라.

지역 변수에는 public이나 static을 붙일 수 없도록 문법이 막고 있다. 어차피 메소드 안에서만 존재하고 메소드에서 나오면 없어지기 때문이다.

static

객체 생성 없이 필드(전역 변수global variable)나 메소드를 생성할 때 붙이는 키워드이다. 메모리 공간에 하나만 존재하고 공유가 가능하므로 클래스 전체에서 공유가 필요할 때 붙이면 된다.

static끼리는 서로 호출할 수 있지만, static 안에서 인스턴스 멤버를 호출할 수 없다. static이 있을 때 인스턴스 멤버가 존재하지 않을 수 있기 때문이다.

static이 변수에 붙으면 상술한 기능을 갖고, 메소드에 붙으면 단독으로 사용 가능하며(main) 상속 시 오버라이딩이 불가능하고, 클래스에 붙으면 상속이 불가능하다.

메소드

함수(function)과 유사하지만 input이나 output이 없을 수도 있다는 것이 다르다. (둘 다 없는 것도 가능)
메소드를 사용하여 코드의 재사용성을 높이고 중복을 최소화하며 구조화를 통해 main함수의 슬림화를 꾀할 수 있다.

int attackSkill (int attackStats) {
    int damage = attackStats * 1.25;
    return damage;
} 

attackSkill이란 메소드는 attackStats라는 매개변수를 받아서 1.25배 뻥튀기하여 damage에 저장하고, 그것을 int로 반환한다. 이름 왼쪽의 int는 반환타입으로, 반드시 이 타입과 맞게 반환(return)이 이루어져야 한다. 반환할 것이 없으면 void로 설정하면 된다.

메소드를 호출할 때는 매개변수에 오만 값이 다 들어올 수 있다고 가정하고 알맞은 타입, 알맞은 값이 들어왔는지 확인하는 절차(유효성 검사)를 거쳐야 한다. attackStats은 통상적으로 0 이상의 자연수이겠지만, 어떠한 이유로 a라든가 -1324같은 값이 들어오면 원하는 damage 값을 반환할 수 없게 된다.

return

현재 실행중인 메소드를 종료하고 해당 메소드를 실행했던 메소드로 돌아간다. 모든 메소드에는 적어도 하나의 return이 있어야하지만 void일 때 안 넣어도 되었던 이유는 컴파일러가 알아서 넣어주었기 때문이다. 조건식 등으로 return이 무조건 실행되리라는 보장이 없어도 에러를 뱉는다.

생성자

인스턴스가 생성될 때 호출되는 인스턴스 초기화 메소드이다. 필수로 생성해야 하며, 사용자가 정의한 생성자가 없으면 컴파일러가 기본 생성자(default constructor)를 생성해준다. 클래스 이름과 같아야 하며, return 값이 없다(생략됨).

this()와 this가 처음 나오는데 더럽게 헷갈린다. this라는 단어만 같이 쓸 뿐, this는 변수고 this()는 생성자라서 완전히 다른 것이다. 간단히 생각하자. this는 매개변수와 인스턴스 변수 이름이 같은 경우에 인스턴스 변수 앞에 this를 붙여주면 되고, this()로 다른 생성자를 호출해오면 되는 것이다.

this는 인스턴스 자신을 가리키는 참조변수이기 때문에 전술한 이유로 static과는 같이 쓸 수 없다.

0개의 댓글