본문 바로가기
프로그래밍언어/Java

[자바의 정석] 06. 객체지향 프로그래밍Ⅰ(1)

by qkzkdo 2023. 7. 29.
728x90

1. 객체지향언어

1.2 객체지향언어

객체지향언어(설계) = 프로그래밍언어+객체지향 개념(규칙)

 

핵심개념

  1. 캡슐화
  2. 상속
  3. 추상화
  4. 다형성★

갹체지향 언어의 주요 특징

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

 

 

2. 클래스와 객체

2.1 클래스와 객체의 정의와 용도

클래스 왜 필요? 객체(제품)를 생성하기 위해

객체(제품) 왜 필요? 객체를 사용하기 위해

객체(TV)를 사용한다는 것은? 객체가 가진 속성(변수)과 기능(메서드)을 사용하려고

 

클래스란? ‘객체를 정의해 놓은 것’. ‘객체의 설계도 또는 틀’

 

클래스의 정의 : 클래스란 객체를 정의해 놓은 것이다.

클래스의 용도 : 클래스는 객체를 생성하는데 사용된다.

객체의 정의 : 실제로 존재하는 것. 사물 또는 개념

객체의 용도 : 객체가 가지고 있는 기능과 속성에 따라 다름

유형의 객체 : 책상, 의자, 자동차, TV와 같은 사물

무형의 객체 : 수학공식, 프로그램 에러와 같은 논리나 개념

객체의 사전적 정의 - ‘실제로 존재한는 것’

 

클래스를 정의하고 클래스를 통해 객체를 생성하는 이유는 설계도를 통해서 제품을 만드는 이유와 같다.

2.2 객체와 인스턴스

클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화(instantiate)라고 하며,

어떤 클래스로부터 만들어진 객체를 그 클래스의 인스턴스(instance)라고 한다.

클래스(설계도) —인스턴스화(제품생성)—> 인스턴스(객체) 제품(사용)을 만드는 것.

 

2.3 객체의 구성요소 - 속성과 기능

객체 = 속성(변수)+기능(메서드) 의 집합

객체가 가지고 있는 속성과 기능을 그 객체의 멤버(구성원, member)라 한다.

클래스로부터 객체를 생성하면, 클래스에 정의된 속성과 기능을 가진 객체가 만들어지는 것이다.

속성(property) : 멤버변수(menber variable), 특성(attribute), 필드(field), 상태(state)

기능(function) : 메서드(method), 함수(function), 행위(behavior)

class Tv { // Tv클래스(Tv설계도)
	// 속성(변수)
	String color; // 색깔
	boolean power; // 전원상태
	int channel; // 채널

	// 기능(메서드)
	void power() { power = !power; }
	void channelUp() { channel++; }
	void channelDown() { channel--; }
//일반적으로 멤버변수를 먼저 선언하고 메서드를 선언한다.
//멤버변수느 멤버변수끼리 메서드는 메서드끼리 모아놓는다.

각 변수의 자료형은 속성의 값에 알맞은 것을 선택해야한다.
power의 값이 true면 false로, false면 true로 변경하는 일을 한다.

 

2.4 인스턴스의 생성과 사용

Tv t = new Tv();
Tv타입 / 참조변수 / 대입연산자 / new연산자(인스턴스생성) / 기본 생성자(호출)

 

객체 : 모든 인스턴스를 대표하는 일반적 용어

인스턴스 : 특정 클래스로부터 생성된 객체(ex. iv 인스턴스)

Tv클래스를 선언한 것은 Tv 설계도를 작성한 것에 불과하므로, Tv인스턴스를 생성해야 제품(Tv)을 사용할 수 있다.

<객체 생성>
클래스명 변수명; // 클래스의 객체를 참조하기 위한 참조변수를 선언
변수명 = new 클래스명(); // 클래스의 객체를 생성 후, 객체의 주소를 참조변수에 저장

Tv t; // Tv클래스 타입의 참조변수 t를 선언
//⑴참조변수(리모콘) 객체에서는 리모콘이 꼭 필요
t = new Tv(); // Tv인스턴스를 생성한 후, 생성된 Tv인스턴스의 주소를 t에 저장
//⑵객체 생성
//⑶대입연산자를 통해 리모콘과 객체를 연결
class Tv { 
	// Tv의 멤버 = 6개
	// Tv의 속성(멤버변수)   
	String color;           // 색상 
	boolean power;         	// 전원상태(on/off) 
	int channel;           	// 채널 
	
	// Tv의 기능(메서드) 
	void power()   { power = !power; }  // TV를 켜거나 끄는 기능을 하는 메서드  
	void channelUp()   {  ++channel; }  // TV의 채널을 높이는 기능을 하는 메서드 
	void channelDown() { --channel; }   // TV의 채널을 낮추는 기능을 하는 메서드  
}
class Ex6_1 { 
	public static void main(String args[]) { 
		//객체(제품)생성
		Tv t;                 // Tv인스턴스를 참조하기 위한 변수 t를 선언       
		t = new Tv();         // Tv인스턴스를 생성한다. 
		//객체(제품)사용 /리모콘을 통해서 꼭 접근해야함.
		t.channel = 7;        // Tv인스턴스의 멤버변수 channel의 값을 7로 한다. 
		t.channelDown();      // Tv인스턴스의 메서드 channelDown()을 호출한다.
		//메서드가 가지고 있는 문장들이 실행됨
		System.out.println("현재 채널은 " + t.channel + " 입니다."); 
	} 
}

 

1. Tv t;

Tv 클래스 타입의 참조변수 t를 선언한다. 메모리에 참조변수 t를 위한 공간이 마련된다.

2. t = new Tv();

연산자 new에 의해 Tv클래스의 인스턴스가 메모리의 빈 공간에 생성된다.

멤버변수는 각 자료형에 해당하는 기본값으로 초기화된다.

 

그 다음에는 대입연산자(=)에 의해서 생성된 객체의 주소값이 참조변수 t에 저장된다.

이제는 참조변수 t를 통해 Tv인스턴스에 접근할 수 있다.

3. t.channel = 7;

인스턴스 멤버변수(속성)를 사용하려면 ‘참조변수.멤버변수’와 같이 하면 된다.

4. t.channelDown();

참조변수 t가 참조하고 있는 Tv인스턴스의 channelDown메서드를 호출한다.

5. System.out.println(”현재 채널은” + t.channel + “입니다”);

t.channel의 값을 출력한다.

 

인스턴스는 참조변수를 통해서만 다룰 수 있으며, 참조변수의 타입은 인스턴스의 타입과 일치해야한다.

✏️클래스가 2개 있는 경우 main메서드가 있는 클래스이름을 소스파일 이름으로 해야 이클립스가 자동으로 실행해줌

  • 같은 클래스에서 생성되었을지라도 각 인스턴스의 속성(멤버변수)은 서로 다른 값을 유지할 수 있으며, 메서드의 내용은 모든 인스턴스에 대해 동일하다.
  • 둘 이상의 참조변수가 하나의 인스턴스를 가리키는(참조하는)것은 가능하지만 하나의 참조변수로 여러 개의 인스턴스를 가리키는 것은 가능하지 않다.

 

2.5 객체 배열 == 참조변수 배열

객체배열은 참조변수들을 하나로 묶은 참조변수 배열인 것이다.

//배열로 바꿈
//Tv타입의 참조변수x3
Tv tvArr = new Tv[3];

각 요소는 참조변수의 기본값인 null로 자동 초기화 된다. 그리고 이 객체 배열은 3개의 객체, 정확히는 객체의 주소를 저장할 수 있다.

객체 배열을 생성하는 것은, 그저 객체를 다루기 위한 참조변수들이 만들어진 것을 뿐, 객체를 생성해서 객체 배열의 각 요소에 저장하는 것을 잊으면 안된다.

 

2.6 클래스의 또 다른정의(클래스=데이터+함수)

클래스

  1. 설계도
  2. 데이터+함수
  3. 사용자 정의 타입

 

1.클래스 - 데이터와 함수의 결합

  1. 변수 : 하나의 뎅터를 저장할 수 있는공간
  2. 배열 : 같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간
  3. 구조체 : 서로 관련되 여러 데이터를 종류에 관계없이 하나의 집합으로 저장할 수 있는 공간
  4. 클래스 : 데이터와 함수의 결합(구조체+함수)

 

2.클래스 - 사용자정의 타입(user=defined type)

  1. 원하는 타입을 직접 만들 수 있다.
  2. 클래스가 곧 사용자정의타입

 

시간 데이터는 다음과 같은 추가적인 제약조건이 있다.

  1. 시,분,초는 모두 0보다 크거나 같아야 한다.
  2. 시의 범위는 0~23, 분과 초의 범위는 0~59 이다.

 

 

3. 변수와 메서드

3.1 선언위치(3가지)에 따른 변수의 종류

변수는 클래스변수, 인스턴스변수, 지역변수 모두 세 종류가 있다.

변수 종류를 결정짓는 중요한 요소는 ‘변수의 선언된 위치’

 

1.인스턴스변수

  • 생성시기 : 인스턴스가 생성되었을 때
  • 인스턴스 변수의 값을 읽어오거나 저장하기 위해서는 먼저 인스턴스를 생성해야한다.
  • 인스턴스마다 독립적인 저장공간을 가짐
  • 인스턴스마다 고유한 상태를 유지해야하는 속성의 경우, 인스턴스변수로 선언

 

2.클래스변수

  • 생성시기 : 클래스가 메모리에 올라갈 때
  • 인스턴스변수 앞에 static을 붙이면 클래스 변수
  • 모든 인스턴스가 공통된 저장공간(변수)을 공유하게 됨
  • 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 속성의 경우, 클래스변수 선언 ’클래스이름.클래스변수’와 같은 형식으로 사용

 

3.지역변수

  • 생성시기 : 변수의 선언문이 수행되었을 때
  • 메서드 내에 선언, 메서드 내에서만 사용, 메서드가 종료되면 소멸
  • for문 while문 블럭 내에 선언된 지역변수는 블럭내에서만 사용, 블럭벗어나면 소멸됨

 

class Variables {
	//클래스영역
	int iv;	//인스턴스변수
	static int cv;	//클래스변수(static변수, 공유변수)
	
	void method() {
		int lv = 0;	//지역변수
	}//메서드영역
}

 

3.2 클래스변수와 인스턴스변수

인스턴스변수는 인스턴스가 생성될 때 마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로, 항상 공통된 값을 갖는다.

 

클래스변수를 사용할 때는 Card.width와 같이 ‘클래스이름.클래스변수’의 형태로 하는 것이 좋다.

인스턴스변수는 인스턴스가 생성될 때 마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로, 항상 공통된 값을 갖는다.

 

3.3 메서드

메서드(=명령문 집합) : 작업단위로 문장들을 묶어서 이름을 붙인 것

‘메서드(method)’는 특정 작업을 수행하는 일련의 {문장들}을 하나로 묶은 것이다.

어떤 값을 입력하면 이 값으로 작업을 수행해서 결과를 반환한다.

 

제곱근을 구하는 메서드 ‘Math.sqrt()’는 4.0을 입력하면 2.0을 결과로 반환한다.

 

메서드의 장점

  • 코드의 중복을 줄일 수 있다.
  • 코드의 관리가 쉽다
  • 코드를 재사용 할 수 있다.
  • 코드가 간결해서 이해하기 쉬워진다.

메서드가 작업을 수행하는데 필요한 값만 넣고 원하는 결과를 얻으면 될 뿐, 즉, 메서드에 넣을 값(입력)과 반환하는 결과(출력)만 알면 되는 것이다.(메서드 내부를 블랙박스 라고도함)

 

메서드를 사용하는 이유

1. 높은 재사용성(reusability)

  • Java API 처럼 한번 만들어 놓은 메서드는 몇 번이고 호출할 수 있다.

 

2. 중복된 코드의 제거

  • 반복되는 문장들을 묶어서 하나의 메서드로 작성해 놓으면, 메서드를 호출하는 한 문장으로 대체할 수 있다. 

 

3. 프로그램의 구조화

  • 큰 규모의 프로그램에서는 문장들을 작업단위로 나눠서 여러 개의 메서드에 담아 프로그램의 구조를 단순화시키는 것이 필수적이다.
  • main메서드는 프로그램의 전체 흐름이 한 눈에 들어올 정도로 단순하게 구조화하는 것이 좋다.
  • 처음에 프로그램을 설계할 때 내용이 없는 메서드를 작업단위로 만들어 놓고, 하나씩 완성해가는 것도 프로그램을 구조화하는 좋은 방법이다.

 

3.4 메서드의 선언과 구현

메서드 = 선언부 + 구현부

메서드를 정의한다는 것은 선언부와 구현부를 작성하는 것

//메서드 선언부
//반환타입 : 메서드가 작업한 작업결과의 타입
반환타입 메서드명 ( 타입 변수명, 타입 변수명, .../*매개변수(작업에 필요한 값들)*/ )
//메서드 구현부
{ //메서드 호출시 수행될 코드(메서드가 작업을 수행하는 코드) }

int add(int a, int b) {  //반환값이 없는 경우에는 반환타입으로 void를 적어줌
  //매개변수도 메서드 내에 선언된 것으로 간주되므로 지역변수이다.
	int result = a + b;
	return result; //호출한 메서드로 결과를 반환한다.
}//메서드영역

 

메서드 선언부(method declaration, method header)

메서드이름, 매개변수 선언, 반환타입으로 구성

메서드가 작업을 수행하기 위해 어떤 값들을 필요로 하고 작업의 결과로 어떤 타입의 값을 반환하는지에 대한 정보를 제공한다.

객체지향 개념에서 메서드는 함수를 지정하는 것

 

매개변수 선언(parameter declaration)

매개변수는 메서드가 작업을 수행하는데 필요한 값들(입력)을 제공받기 위한 것 

입력해야할 값의 개수가 많은 경우 배열이나 참조변수를 사용하면 된다.

매개변수도 메서드 내에 선언된 것으로 간주되므로 ‘지역변수’이다.

 

매서드 이름(method name)

변수의 명명규칙대로 작성하면 된다.

특정 작업을 수행하므로 ‘add’처럼 동사인 경우가 많음

 

반환타입(return type)

메서드의 작업수행 결과인 ‘반환값’의 타입을 적는다.

반환값이 없는 경우 반환타입으로 ‘void’를 적는다.

 

메서드의 구현부(method body, 메서드 몸통)

메서드의 선언부 다음에 오는 괄호{}를 ‘메서드의 구현부’라고 한다.

여기에 메서드를 호출했을 때 수행될 문장들을 적는다.

 

return문

메서드 반환타입이 void가 아닌 경우, 구현부 안에 ‘return 반환값;’이 반드시 포함되어있어야한다.

이 문장은 작업을 수행한 결과인 반환값을 호출한 메서드로 전달하는데, 이 값의 타입은 반환타입과 일치하거나 적어도 자동 형변환이 가능한 것이어야 한다.

 

지역변수(local variable)

메서드 내(메서드 영역)에 선언된 변수 지역변수는 메서드 내에서만 사용할 수 있으므로 서로 다른 메서드라면 같은 이름의 변수를 선언해도 된다. 

 

3.5 메서드의 호출(call)

메서드를 정의했어도 호출되지 않으면 아무 일도 일어나지 않는다. 메서드를 호출해야만 구현부{}의 문장들이 수행된다

메서드이름(값1, 값2, ...);  // 메서드를 호출하는 방법
print99danAll(); //void print99danAll()을 호출
int result = add(3, 5);  //int add(int x, int y)를 호출하고, 결과를 result에 저장
//반환타입이 void가 아닌 경우,
add(3 ,5);  //ok. 메서드 add가 반환한 결과를 사용하지 않아도 된다.

 

인자(argument)와 매개변수(parameter)

메서드를 호출할 때 괄호()안에 지정해준 값들을 ‘인자’ 또는 ‘인수’라고 하는데 인자의 개수와 순서는 호출된 메서드에 선언된 매개변수와 일치해야 한다.

인자 타입은 매개변수와 일치하거나 자동 형변환 가능한 것이어야 한다.

 

메서드의 실행흐름

같은 클래스 내의 메서드끼리는 참조변수를 사용하지 않고도 서로 호출이 가능하지만 static메서드는 같은 클래스 내의 인스턴스 메서드를 호출할 수 없다.

메서드를 호출하기 위해서는 메서드가 선언된 클래스의 인스턴스를 생성한 다음 참조변수를 통해 호출해야 한다.

class MyMath {
	int add (int a, int b) {
		int result = a + b;
		return result;
	}
}
public class MyMathTest {

	public static void main(String[] args) {
		MyMath m = new MyMath(); // 메서드 호출하기 위해서는 먼저 MyMath클래스의 인스턴스를 생성해야함
		int value = m.add(1,3); //생성 후 참조변수를 통해야함
		//int value = add(1,3);
		//int value = 4;
		System.out.println(value);
	}
}

메서드가 호출되면 지금까지 실행중이던 메서드는 실행을 잠시 멈추고 호출된 메서드의 문장들이 실행된다.

사실은 호출한 자리를 반환값이 대신하고 대입연산자에 의해 이 값이 변수 value에 저장된다.

 

3.6 return문

return문은 현재 실행중인 메서드를 종료하고 호출한 메서드로 되돌아간다.

* 모든 메서드에는 적어도 하나의 return문이 있어야함 void는 컴파일러가 메서드 마지막에 return;을 자동적으로 추가해줌

 

매개변수의 유효성 검사

메서드의 구현부{}를 작성할 때, 제일 먼저 해야 하는 일이 매개변수의 값이 적절한 것인지 확인하는 것이다.

 

3.7 JVM의 메모리 구조

응용프로그램이 실행되면, JVM은 시스템으로부터 프로그램을 수행하는데 필요한 메모리를 할당받고 JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.

 

주요 영역

1. 메서드 영역(method area)

클래스 데이터 저장, 클래스 변수도 함께 생성됨

 

2. 힙(heap)

인스턴스가 생성되는 공간, 인스턴스 변수들이 생성되는 공간

 

3. 호출스택(call stack 또는 execution stack)

메서드 수행에 필요한 메모리가 저장되는 공간

메서드가 호출되면, 호출스택에 호출된 메서드를 위한 메모리가 할당된다.

메서드가 작업을 마치면 할당되었던 메모리공간은 반환되어 비워진다.

 

스택 : 밑이 막힌 상자, 위에 차곡차곡 쌓인다.

 

호출스택의 특징 정리

  • 메서드가 호출되면 수행에 필요한 만큼 메모리를 스택에 할당받는다.
  • 메서드가 수행을 마치고나면 사용했던 메모리를 반환하고 스택에서 제거된다.
  • 호출스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드이다.
  • 아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드이다. (맨 위의 메서드 하나만 실행중, 나머지는 대기중)

반환타입이 있는 메서드는 종료되면서 결과값을 자신을 호출한 메서드에게 반환한다. 대기상태에 있던 호출한 메서드(caller)는 넘겨받은 반환값으로 수행을 계속 진행하게 된다.

 

3.8 기본형 매개변수와 참조형 매개변수

자바에서는 메서드를 호출할 때 매개변수로 지정한 값을 메서드의 매개변수에 복사해서 넘겨준다.

매개변수의 타입이 기본형(primitive type)일 때는 기본형 값이 복사되겠지만,

참조형(reference type)이면 인스턴스의 주소가 복사된다.

기본형(8개)매개변수 : 변수의 값을 읽기만 할 수 있다.
참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다.

 

3.9 참조형 반환타입

매개변수 뿐만 아니라 반환타입도 참조형이 될 수 있다.(반환하는 값이 참조형) 모든 참조형 타입의 값은 ‘객체의 주소’이므로 그저 정수값이 반환되는 것일 뿐 특별할 것이 없다.

“반환타입이 ‘참조형’이라는 것은 메서드가 ‘객체의 주소’를 반환한다는 것을 의미한다.”

 

3.11 클래스 메서드(static메서드)와 인스턴스 메서드(iv사용여부)

인스턴스메서드는 인스턴스 변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드이다.

메서드 중에서 인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드를 사용하지 않는)메서드를 클래스 메서드(static메서드)로 정의한다.

 

  1. 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙인다.
  2. 클래스 변수(static변수)는 인스턴스를 생성하지 않아도 사용할 수 있다.
  3. 클래스 메서드(static메서드)는 인스턴스 변수를 사용할 수 없다
  4. 메서드 내에서 인스턴스 변수를 사용하지 않는다면, ststic을 붙이는 것을 고려한다. 메서드 호출시간이 짧아지므로 성능이 향상된다.
클래스의 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있는지 살펴보고 있으면, static을 붙여준다.
작성한 메서드 중에서 인스턴스 변수 인스턴스 메서드를 사용하지 않는 메서드에 static을 붙일 것을 고려한다.

 

▶인스턴스 메서드

  • 인서턴스 생성 후 ‘참조변수.메서드이름()’으로 호출
  • 인스턴스멤버(iv,im)와 관련된 작업을 하는 메서드
  • 메서드 내에서 인스턴스 변수 사용 가능

▶static 메서드(클래스 메서드)

  • 객체생성 없이 ‘클래스이름.메서드이름()’으로 호출
  • 인스턴스멤버(iv,im)와 관련 없는 작업을 하는 메서드
  • 메서드 내에서 인스턴스변수 사용 불가

 

3.12 클래스 멤버와 인스턴스 멤버간의 참조와 호출

같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다. 단, 클래스멤버가 인스턴스 멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다.

 

 

 

출처 : 남궁성. 「자바의 정석」. 도우출판. 2016

728x90