객체지향 프로그래밍 (변수/클래스)

J·2020년 11월 15일
0

진짜 보기만 해도 토나오는 글자!
해도해도 늘지 않는 것 같다.
남궁성 저자님의 오프라인 강의를 꾸준히 다녔는데, 그 때 말씀하시길, "몇 번 읽고 이해가 갔으면 너도 나도 프로그래밍 했을 것" 이라며 그냥 이해가 가는 순간은 언젠가 오게 되어있으니 꾸준히 열심히 반복해서! 공부하라고 하셨다.


객체지향언어가 뭔데?

규칙들을 이용해 코드 간 서로 관계를 맺어 줌으로써 보다 유기적으로 프로그램을 구성하는 것이다. 주요 특징은 아래 세 가지!

  1. 코드의 재사용성 : 기존의 코드를 이용해 새로운 코드를 쉽게 작성할 수 있다.
  2. 코드 관리의 용이 : 관계를 이용해 적은 노력으로 쉽게 코드를 변경할 수 있다.
  3. 신뢰성이 높은 프로그래밍 : 제어자와 메서드를 이용해 데이터를 보호하고 올바른 값을 유지하도록 하며, 코드의 중복을 제거하여 코드의 불일치로 인한 오동작을 방지할 수 있다.

정리하자면 재사용성, 유지보수, 중복된 코드의 제거! 이 세 가지 관점에서 보면 된다.
제품을 만들 때를 생각해보자. 부품을 먼저 개발하고, 이 부품들을 조립해서 제품을 만든다. 소프트웨어를 개발할 때에도 부품에 해당하는 객체를 만들고, 이것들을 하나씩 조립해서 완성된 프로그램을 만드는 기법을 객체지향 프로그래밍이라고 한다.

객체? 클래스?

  • 객체 : 부품
  • 클래스 : 설계도

위에서 제품을 만들 때 부품을 만들고, 조립해 제품을 만든다고 했다. 그럼 프로그래밍은 객체를 만들고, 객체를 조립해 프로그램을 만드는 것. 클래스는 객체를 생성하는 데 필요한 것이다. 난 이것을 설계도라고 표현하는 걸 많이 봤다.

객체와 인스턴스

객체 = 속성 + 기능

  • 속성 : 멤버변수, 특성, 필드, 상태
  • 기능 : 메서드, 함수, 행위

인스턴스는 뭐지?

클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화라고 하며, 어떤 클래스로부터 만들어진 객체를 그 클래스의 인스턴스라고 한다. 같은 의미이므로 엄격히 구분할 필요는 없다. 간단히 객체=인스턴스 라고 생각하자.

객체의 설계도인 클래스

클래스에는 객체를 생성하기 위한 필드와 메소드가 정의되어 있다!

클래스를 선언해보자!

생성할 객체의 이름으로 클래스를 만들면 된다. 클래스이름.java라는 소스파일을 생성하는 것이다.

객체지향 프로그래밍 개발이란,

  1. 클래스를 설계하고
  2. 설계된 클래스를 가지고 사용할 객체를 생성한 후
  3. 생성된 객체를 이용하는 것

객체

필드

필드는 속성을 말한다.

{ } 중괄호가 없이 변수를 선언하듯 필드를 선언하면 된다. 클래스 중괄호 안 어디서든 선언이 가능하다. 생성자와 메소드 중괄호 블록이 아니기만 하면 된다. (생성자와 메소드 내에서 선언되는 것들은 로컬변수로, 생성자와 메소드가 종료되면 소멸된다.) 초기값이 지정되지 않은 필드들은 객체 생성 시 자동으로 기본 초기값으로 설정된다.

필드를 사용할 때에는 반드시 객체를 생성한 뒤 사용해야 한다.

몇 번이고 공부했던 부분인데, stack 영역과 heap 영역을 나누어 생각하니 이해하는데 큰 도움이 됐다. 그림을 그려가며 공부를 하라고 했던 이야기가 이거구나! 싶었다.

객체를 생성하면, heap(메모리) 영역에 객체가 생성된다. stack 영역에 있는 클래스 변수에는 이 heap 영역에 저장된 객체의 주소값이 저장된다. 이 주소를 통해 heap 영역의 객체에 접근해야한다.

클래스 내부의 생성자나 메소드에서 사용할 경우 단순히 필드 이름으로 읽고 수정하면 되지만, 외부에서 사용할 때에는 반드시 객체를 생성한 뒤 사용해야 한다. 객체가 없으면 당연히 필드도 없다.

생성자

객체의 초기화를 담당한다.

생성자(Constructor)는 new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출된다. 이 때 객체를 초기화하는 것!

new 연산자에 의해 생성자가 성공적으로 실행되면 heap 영역에 객체가 생성되고, 객체의 주소가 리턴된다. 리턴된 객체의 주소는 클래스 타입 변수에 저장되어 객체에 접근할 때 이용된다. (책에서 발췌한 부분인데 위에서 정리한 내용이 그대로임.. 머쓱)

기본 생성자

모든 클래스는 생성자가 반드시 존재하며, 하나 이상을 가질 수 있다. 생성자 선언을 생략하면 클래스 이름의 { } 중괄호가 빈 기본 생성자를 컴파일러가 알아서 바이트코드에 추가해준다.

생성자 선언

클래스(매개변수선언, ...) {
	// 객체의 초기화 코드
    	}

메소드와 비슷한 모양이지만, 리턴 타입이 없고, 클래스 이름과 동일하다.
매개변수 선언은 생략할 수도 있고, 여러 개를 선언하기도 한다. 매개변수는 new 연산자로 생성자를 호출할 때, 외부의 값을 생성자 블록 내부로 가져오는 역할을 한다.

클래스가 명시적으로 선언되어 있을 경우, 기본 생성자가 따로 선언되어있지 않을 때, 선언되어 있는 생성자를 이용해 객체를 생성해야 한다. 아니면 기본 생성자를 직접 선언해주어도 된다.

필드 초기화

객체가 생성횔 때 필드는 기본 초기값으로 자동 설정된다. 만약 다른 값으로 초기화를 하고싶다면?

  1. 필드를 선언할 때 초기값을 주거나,
  2. 생성자에서 초기값을 준다!

텍스트로 설명하자니 복잡해져서.. 모르겠다면 책을 읽어보자. 귀찮아서 그러는거 아님 ㅠ ㅎㅎ

생성자 오버로딩

위에서 말했던 2번과 연결되는 내용인것 같다. 생성자는 여러 번 선언해도 좋다고 했다.

외부에서 제공되는 다양한 데이터를 이용해 객체를 초기화하려면 생성자도 다양해야 한다.
다양한 방법으로 객체를 생성할 수 있도록 생성자 오버로딩을 제공한다.

생성자 오버로딩이란, 매개변수를 달리하는 생성자를 여러 개 선언하는 것을 말한다.

이해한 것을 줄글로 늘어놓으려니 참 어렵다. 오늘은 이해했다. 정말로!

다른 생성자 호출

생성자 오버로딩이 많아질 경우 생성자 간 중복된 코드가 발생하기도 한다. 이 경우에는 this()를 이용해 코드의 중복을 줄일 수 있다.

이건 분명 여러번 했던 기억이 있는데 오늘 다시 읽으니 참 새롭다.

여러 생성자를 선언하다 보면 주로 매개변수가 가장 많은 놈이 하나 있다. 얘 하나만 제대로 선언을 하고, 나머지 생성자에서는 그 생성자를 호출하는 것이다. 이 때, 그 생성자를 this()를 사용해 호출하는 것이다.

이것도 책 보면 정말 깔끔한데..!

예를 들어보자.

Car(String model) {
	this.model = model;
    	this.color = "은색";
       	this.maxSpeed = 250;
        }
Car(String model, String color) {
	this.model = model;
    	this.color = color;
       	this.maxSpeed = 250;
        }
Car(String model, String color, int maxSpeed) {
	this.model = model;
    	this.color = color;
       	this.maxSpeed = maxSpeed;
        }

이렇게 세 개의 생성자를 만들었다.
여기에서 매개변수가 가장 많은 마지막 생성자를 보니,
위 두 개의 생성자에서 선언했던 것들이 포함되어 있다.
이것을 이용해 위 두 개의 생성자를 줄여보자.

Car(String model) {
	this(model, "은색", 250);
       }
Car(String model, String color) {
	this(model, color, 250);
       }
Car(String model, String color, int maxSpeed) {
	this.model = model;
   	this.color = color;
      	this.maxSpeed = maxSpeed;
       }

마지막에 있는 생성자는 그대로 써주고 위 생성자들은 this를 이용해 가장 아래의 생성자를 호출해주었다. 많이 깔끔해졌다!

메소드

는 나중에 다시 추가하기!

-- 추가 완료 --






  • 참고 : 이것이 자바다 (by 신용권님)

0개의 댓글