클래스, 인스턴스, 객체 ?

객체(Object) : 소프트웨어 세계에 구현할 대상, 클래스에 정의댄 대로 메모리에 생성된 것

클래스(Class) : 객체를 생성하기 위한 설계도, 틀

인스턴스(Instance) : 설계도에 따라 구현된 실체

 

1. 객체지향 프로그래밍

객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 컴퓨터 프로그래밍(하나 이상의 추상 알고리즘을 특정한 프로그래밍 언어를 이용해 컴퓨터 프로그램을 구현)의 패러다임 중 하나이다. 컴퓨터 프로그램을 여러개의 독립된 단위인 객체들의 모임으로 파악한 것이다. 각각의 객체는 메세지를 주고받으며 데이터를 처리할 수 있다. 

 

 

 

2. 객체지향언어

객체지향이론의 기본 개념은 '실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물(객체)간의 상호작용이다' 라는 것이다. 이러한 개념으로 다수의 객체를 만들고 객체들끼리 서로 상호작용하며 만드는 프로그래밍 언어를 객체지향언어라고 한다. 코드간에 서로 관계를 맺어주어 보다 유기적으로 프로그램을 구성하는 것이 가능하다. 

객체지향언어의 가장 큰 장점은 코드의 재사용성이 높고 유지보수가 용이하다는 것이다.

재사용성, 유지보수, 중복된 코드의 제거. 이 세 가지의 관점으로 객체지향개념을 이해할 수 있다.

 

 

 

2. 객체지향언어의 장점

1) 코드의 재사용성이 높다.

새로운 코드를 작성할 때 기존의 코드를 이용하여 쉽게 작성 가능하다.

 

2) 코드의 관리가 용이하다.

코드간의 관계를 이용하기 때문에 코드 변경이 쉽다.

 

3) 신뢰성이 높은 프로그래밍을 가능하게 한다.

제어자와 메서드를 이용해서 데이터를 보호하며 올바른 값을 유지하도록 한다. 코드의 중복을 제거하여 코드의 불일치로 인한 오동작을 방지 할 수 있다.

 

 

4. 객체

객체의 사전적 정의는 '실제로 존재하는 것' 이다.  객체지향이론에서는 사물과 같은 유형적인 것뿐만 아니라 개념이나 논리같은 무형적인 것들도 객체로 간주한다. 객체란 실제로 존재하는 사물 또는 개념이다.

프로그래밍에서 객체는 클래스에 정의된 내용대로 메모리에 생성된 것을 의미한다.

객체는 속성과 기능 두종류의 구성요소로 이루어져있어 객체를 속성과 기능의 집합이라고 할 수 있다.객체의 용도는 객체가 가지고 있는 기능과 속성에 따라 다르다. 객체가 가지고 있는 속성과 기능을 그 객체의 멤버(구성원) 이라고 한다.

속성과 기능은 아래와 같은 같은 뜻의 여러가지 용어가 있다.

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

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

여기서도 속성으로는 멤버변수, 기능으로는 메서드 용어를 주로 사용한다.

 

 

 

5. 클래스

5-1. 클래스 - 객체를 정의해놓은 객체의 설계도

클래스는 객체지향이론 관점에서 '객체를 정의해놓은 것' 혹은 '객체의 설계도 또는 틀' 이라고 말할 수 있다. 클래스란 객체를 정의해 놓은것이며 클래스는 객체를 생성하는데 사용되고 객체는 클래스에 정의된 대로 생성된다. 클래스는 단지 객체를 생성하는데 이용되는 것이기 때문에 프로그래밍을 할 때 먼저 클래스를 작성한 다음에 클래스로부터 객체를 생성해서 사용한다. (객체를 사용한다는 것은 객체가 가지고 있는 속성과 기능을 사용한다는 뜻이다.)

JDK에서는 프로그래밍을 위해 많은 유용한 클래스를 기본적으로 제공하며 이 클래스들을 이용해서 원하는 기능의 프로그램을 보다 쉽게 작성할 수 있다.

 

 

class Tv {
	String color;
	boolean power;
	int channel;

void power(){power = !power;}
void channelUp(){++channel;}
void channelDown(){--channel;}
}

Tv 클래스를 생성했다. 

color, power, channel 은 Tv클래스로 생성될 Tv 객체(인스턴스)의 속성(멤버변수, 필드) 이고

power(), channelUp(), channelDown()은 Tv 객체(인스턴스)의 기능(메서드) 이다.

이 Tv클래스로 color, power, channel 속성을 가지고 power(), channelUp(), channelDown() 기능(행위)를 가진 Tv객체를 만들 수 있는 것이다. -> 클래스로 해당 속성과 기능을 가진 객체를 생성할 수 있다.

 

 

 

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

클래스를 위와 같이 '객체를 생성하기 위한 틀'으로 정의한 것은 객체지향이론의 관점에서 비롯된 것이다.

프로그래밍적인 관점에서 클래스의 정의와 의미는 이와 구별된다.

 

프로그래밍적인 관점에서의 클래스 정의

1. 데이터와 함수의 결합

2. 사용자정의 타입

 

프로그래밍 언어에서 데이터 처리를 위해서는 데이터 저장형태가 '변수->배열->구조체->클래스'로 확장된다.

 

변수 : 하나의 데이터를 저장할 수 있는 공간

배열 : 같은 종류의 여러 데이터를 하나의 집합으로 저장할 수 있는 공간

구조체 : 서로 관련된 여러 데이터를 종류에 관계없이 하나의 집합으로 저장할 수 있는 공간

클래스 : 데이터와 함수의 결합 (구조체 + 함수)

 

 

자바와 같은 객체지향언어에서는 변수(데이터)와 함수를 하나의 클래스에 정의해서 서로 관계가 깊은 변수와 함수들을 함께 다룰 수 있게 하였다. 서로 관련된 변수들을 묶어서 하나의 타입으로 새로 추가하는 것을 사용자 정의 타입이라고 하고 객체지향언어에서는 클래스가 사용자 정의 타입이다.

 

 

 

 

6. 인스턴스

클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화라고 하며, 어떤 클래스로부터 만들어진 객체를 그 클래스의 인스턴스(instance)라고 한다.

클래스로부터 생성된 것이 객체라고 했는데, 클래스로부터 생성된 객체를 '인스턴스'라고 한다는 것이다. 결국 인스턴스는 객체와 같은 의미이지만 객체는 모든 인스턴스를 대표하는 포괄적인 큰 개념이고, 인스턴스는 보다 구체적인 의미를 가지고 있다. 인스턴스는 어떤 클래스로부터 만들어진 것인지가 강조된다. 

 

 

 

7. 인스턴스의 생성과 사용

클래스명 변수명;   (해당 클래스 타입의 참조변수를 선언한다)

변수명 = new 클래스명();   (클래스의 객체를 생성 후 객체의 주소를 참조변수에 저장한다, 참조변수는 클래스의 객체를 참조한다)

class TvTest1{
public static void main(String args[]){
Tv t;		
t = new Tv();
t.channel = 7;
t.channelDown();
System.out.println("현재 채널은" + t.channel + " 입니다."
//실행결과 : 현재 채널은 6 입니다.

(1) Tv t

Tv클래스 타입의 참조변수 t를 선언했다. 메모리에 참조변수 t를 위한 공간이 생긴다. 아직 인스턴스를 생성하지 않았기 때문에 참조변수 t는 아무것도 할 수 없다.

 

(2) t = new Tv()

Tv인스턴스를 생성한다. new 연산자에 의해 Tv클래스의 인스턴스가 메모리의 빈 공간에 생성된다. 이때 멤버변수는 각 자료형에 해당하는 기본값으로 초기화 된다. (String타입의 color는 기본값 null, boolean 타입의 power는 기본값 false, int 타입의 channel은 기본값 0으로 초기화 된다.)

생성된 객체 인스턴스의 주소값을 대입연산자(=)를 통해 참조변수 t에 저장한다.

이제, 참조변수 t를 통해서 Tv인스턴스에 접근할 수 있다. 인스턴스를 다루기 위해서는 참조변수가 반드시 필요하다.

'참조변수 t가 Tv인스턴스를 가리키고 있다.', '참조변수 t가 Tv인스턴스를 참조하고 있다.' 라고 할 수 있는 것이다.

 

(3) t.channel = 7

참조변수 t에 저장된 주소에 있는 인스턴스의 멤버변수 channel에 값 7을 저장한다.

인스턴스의 속성(멤버변수, 필드)를 사용하려면 이렇게 '참조변수.멤버변수' 와 같이 작성하면 된다.

 

(4) t.channelDown()

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

 

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

참조변수 t가 참조하고 있는 Tv인스턴스의 멤버변수 channel에 저장되어 있는 값을 출력한다.

 

 

Tv인스턴스를 사용하려면 Tv클래스 타입의 참조변수가 필요하다.

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

 

 

class TvTest2 {
	public static void main(String args[]) {
		Tv t1 = new Tv();  // Tv t1; t1 = new Tv();를 한 문장으로 가능
		Tv t2 = new Tv();
		System.out.println("t1의 channel값은 " + t1.channel + "입니다.");
		System.out.println("t2의 channel값은 " + t2.channel + "입니다.");
		
       		t2 = t1; //t1이 저장하고 있는 값(주소)를 t2에 저장한다.
		t1.channel = 7;	// channel 값을 7으로 한다.
		System.out.println("t1의 channel값을 7로 변경하였습니다.");

		System.out.println("t1의 channel값은 " + t1.channel + "입니다.");
		System.out.println("t2의 channel값은 " + t2.channel + "입니다.");
	}
}

(1) Tv t1 = new Tv(); Tv t2 = new Tv();

위의 TvTest1 클래스에서 두 문장으로 참조변수를 선언하고, 인스턴스를 생성해서 참조변수에 연결한 것을 한 문장으로 표현했다.

 

(2) t2 = t1;
t1과 t2는 참조변수이므로 인스턴스의 주소를 저장하고 있다.

t2는 기존의 값을 잃고 t1에 저장되어 있던 값이 t2으로 저장된다. t2는 t1이 참조하고 있던 인스턴스를 같이 참조하게 되고 t2가 원래 참조하고 있었던 인스턴스는 더이상 사용할 수 없게 된다.

자신을 참조하고 있는 참조변수가 하나도 없는 인스턴스는 더이상 사용될 수가 없고 가비지컬렉터에 의해 자동으로 메모리에서 제거된다.

(3) t1.channel = 7;

참조변수 t1에 저장된 주소의 인스턴스 채널값을 7로 한다.

 

(4) System.out.println("t1의 channel값은 " + t1.channel + "입니다.");
System.out.println("t2의 channel값은 " + t2.channel + "입니다.");

t1, t2 모두 같은 인스턴스를 참조하고 있기 때문에 t1.channel과 t2.channel의 값은 동일하게 7으로 확인된다.

 

 

둘 이상의 참조변수가 하나의 인스턴스를 가리키는(참조하는) 것은 가능하지만,

참조변수에는 하나의 값(주소)만 저장될 수 있기 때문에 하나의 참조변수로 여러개의 인스턴스를 가리키는것은 불가능하다. 

 

 

 

8. 메서드

8-1. 메서드의 선언과 구현

메서드는 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것이다.

메서드를 사용하는 이유는 높은 재사용성, 중복된 코드의 제거, 프로그램 구조화로 말할 수 있다.

메서드는 선언부와 구현부로 이루어져 있고 메서드를 정의한다는 것은 선언부와 구현부를 작성하는 것이다. 선언부는 메서드명, 매개변수, 반환타입으로 구성된다. 구현부는 선언부 다음에 오는 {} 이고, 메서드를 호출했을 때 수행될 문장들을 포함한다.

메서드의 반환타입이 void가 아닌 경우에는 구현부에 return 반환값;이 포함되어야 한다. 작업을 수행하고 결과를 반환할 때 그 값은 메서드의 반환타입과 일치하거나 자동 형변환이 가능해야 한다.

 

 

8-2. 메서드 호출

메서드를 호출해야만 메서드의 구현부 문장이 수행된다.

메서드이름(값, 값....); 으로 메서드를 호출할 수 있다. 괄호()안에 지정해준 값들을 인자, 인수라고 한다.

인자의 개수는 메서드에 선언된 매개변수의 개수와 일치해야 한다. 인자는 메서드가 호출되면서 매개변수에 대입되므로 인자의 타입은 매개변수 타입과 일치하거나 자동 형변환이 가능해야 한다.

 

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

 

메서드 내부에서 메서드 자신을 다시 호출하는 것은 재귀호출이라고 하고 재귀호출하는 메서드를 재귀 메서드라고 한다. 코드에 재귀호출뿐이면 무한반복에 빠지기 때문에, 무한반복문이 조건문과 함께 사용되는 것처럼 조건문과 같이 사용한다.

 

 

 

8-3. 기본형 매개변수와 참조형 매개변수

메서드의 매개변수를 기본형으로 선언하면 단순히 저장된 값을 얻는다. 변수의 값을 읽기만 할 수 있다. (read only)

메서드의 매개변수를 참조형으로 선언하면 값이 저장된 곳의 주소를 알 수 있기 때문에, 값을 읽어올수도 있고 변경할 수도 있다. (read & write)

 

 

 

 

8-4. 참조형 반환타입 (return)

매개변수뿐만 아니라 반환타입도 참조형이 될수 있다. 반환하는 값이 참조형 타입이라는 것이고, 메서드가 '객체의 주소'를 반환한다는 것이다.

 

 

 

8-5. 클래스메서드(static 메서드)와 인스턴스 메서드

메서드 앞에 static이 붙으면 클래스메서드, 그렇지 않으면 인스턴스 메서드이다.

클래스 변수와 인스턴스변수처럼 클래스메서드도 객체를 생성하지 않고 '클래스이름.메서드이름(매개변수)' 으로 호출할 수 있다. 인스턴스 메서드는 인스턴스 변수처럼 객체를 생성해야만 호출 할 수 있다.

 

인스턴스 메서드

인스턴스 변수(iv)를 필요로 하는 메서드

클래스 메서드

인스턴스와 관계없는(인스턴스 변수 사용하지 않는) 메서드

 

 

 

8-6. 오버로딩(overloading)

한 클래스 내에 같은 이름의 메서드를 여러개 정의하는 것을 메서드 오버로딩, 오버로딩이라고 한다. 하나의 메서드 이름으로 여러 기능을 구현하는 것이다. 오버로딩은 메서드 이름이 같고 매개변수의 개수나 타입이나 순서가 달라야한다. 반환타입은 오버로딩을 구현하는 데 영향을 주지 않는다. 

기존에 없는 새로운 메서드를 정의하는 것이다. 이름이 같을 뿐이다.

 

cf. 오버라이딩(overriding)

조상클래스로부터 상속받은 메서드의 내용을 변경하는 것으로 메서드의 내용만 새로 작성한다. 기존의 메서드를 변경하는 것이다.

1. 조상클래스의 메서드와 이름, 매개변수, 반환타입이 같아야 한다. (선언부 일치)

2. 접근 제어자(public, protected, private, default)는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.

3. 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.

 

 

오버라이딩과 오버로딩은 관계없다.

 

 

 

9. 클래스  변수, 클래스 메서드 / 인스턴스 변수, 인스턴스 메서드

1) 클래스를 설계할 때 멤버변수 중 모든 인스턴스에 공통적으로 사용하는 것에 static을 붙여 클래스 변수로 정의한다. 인스턴스 변수는 인스턴스마다 독립적으로 존재한다.

2) 클래스 변수(static 변수)는 인스턴스를 생성하지 않아도 언제나 사용가능하다. 클래스 변수는 클래스가 메모리에 올라갈 때 자동적으로 생성되기 때문이다.

3) 클래스 메서드(static 메서드)는 인스턴스 변수를 사용할 수 없다. 인스턴스 변수는 인스턴스가 반드시 존재해야 사용할 수 있는데 클래스메서드는 인스턴스 생성없이 호출가능하기 때문에 클래스메서드에서 인스턴스변수의 사용이 금지된다.

인스턴스변수나 인스턴스메서드에서는 static이 붙은 클래스변수나 클래스메서드를 사용하는것이 가능하다.

4) 메서드 내에서 인스턴스 변수를 사용하지 않는다면 static을 붙인다. 메서드 호출시간이 짧아지므로 성능이 향상된다. static을 붙이지 않은 인스턴스 메서드는 실행시에 호출되어야 할 메서드를 찾는 과정이 필요해서 시간이 더 걸리기 때문이다.

 

 

 

 

10. 생성자(constructor)

생성자는 인스턴스가 생성될때 호출되는 인스턴스 초기화 메서드이다. (인스턴스 초기화란 인스턴스변수들을 초기화 하는 것이다.)

생성자의 이름은 클래스의 이름과 같아야하고, 생성자는 리턴값이 없다. 모든 생성자가 반환값이 없으므로 void는 생략한다.

생성자도 오버로딩이 가능해서 하나의 클래스에 여러개의 생성자가 존재할 수 있다. 클래스에 정의된 생성자가 하나도 없을 때는 컴파일러가 자동적으로 기본생성자를 추가하여 컴파일한다. 기본생성자는 매개변수도 없고 내용도 없다.

생성자가 하나라도 있는 경우에는 기본생성자가 자동으로 추가되지는 않는다.

 

생성자 간에도 서로 호출이 가능하다. 한 생성자에서 다른 생성자를 호출할 때는 생성자의 이름으로 클래스이름대신에 this를 사용해야 하고, 반드시 첫줄에서만 호출이 가능하다.