1. 객체지향 프로그래밍
1.1 객체지향언어의 역사
객체지향언어의 기본 개념은 ‘실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용이다.’ 라는 것이다. 객체지향이론은 상속, 캡슐화, 추상화 개념을 중심으로 구체적으로 발전되었다.
1.2 객체지향언어 특징
- 코드의 재사용성이 높다. 새로운 코드를 작성할때 기존의 코드를 이용해 쉽게 작성가능하다.
- 코드의 관리가 용이하다. 코드간의 관계를 이용해 적은 노력으로 쉽게 코드를 변경할 수 있다.
- 신뢰성이 높은 프로그래밍을 가능하게 한다. 제어자와 메서드를 이용해 데이터를 보호하고 올바른 값을 유지하도록 하며, 코드의 중복을 제거해 코드의 불일치로 인한 오동작을 방지한다.
객체지향개념을 학습할때 재사용성, 유지보수 그리고 중복된 코드의 제거 이 3가지 관점에서 보면 보다 쉽게 이해할 수 있다.
2. 클래스와 객체
2.1 클래스와 객체의 정의와 용도
클래스란 객체를 정의해놓은 것으로 객체의 설계도 또는 틀을 말하며 객체를 생성하는데 사용된다.
객체의 사전적인 정의는 ‘실제로 존재하는 것’이다. 우리가 주변에서 볼 수 있는 책상, 의자 , 자동차와 같은 사물들이 곧 객체이며 객체지향이론에서는 사물과 같은 유형적인 것 뿐만 아니라 개념과 논리같은 무형적인 것들도 객체로 간주한다. 프로그래밍에서의 객체는 클래스에 정의된 내용대로 메모리에 생성된 것을 뜻한다.
- 객체의 정의 : 실제로 존재하는 것, 사물또는 개념
- 객체의 용도: 객체가 가지고 있는 기능과 속성에 따라다름
- 유형의 객체 : 책상, 의자, 자동차와 같은 사물
- 무형의 객체 : 수학공식, 프로그램 에러와 같은 논리나 개념
더 자세히말하면 클래스와 객체관계를 제품 설계도와 제품의 관계라고 볼 수 있다. 예를들어 TV 설계도(클래스)와 TV라는 제품(객체)를 정의한 것이며, TV를 만드는게 사용된다. e.f. 제품설계도 - 제품, TV 설계도 - TV, 붕어빵 틀 - 붕어빵
클래스를 정의하고 클래스를 통해 객체를 생성하는 이유는 설계도를 잘 만들어 놓으면 제품을 만드는 일이 쉬워지기 때문이다. 따라서 클래스를 한번만 잘 만들면 매번 객체를 생성할때마다 객체를 어떻게 만들지 고민하지 않아도 된다. 그냥 클래스로부터 객체를 생성해서 사용하기만 하면 된다.
2.2 객체와 인스턴스
클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화(insttantiate)라고하며, 어떤 클래스로부터 만들어진 객체를 그 클래스의 인스턴스(instance)라고한다. 예를들어 TV 클래스로부터 만들어진 객체를 TV 클래스의 인스턴스라고한다. 결국 인스턴스와 객체는 같은 말이다.
하지만 객체는 모든 인스턴스를 포괄하는 의미를 갖고 있으며, 인스턴스는 어떤 클래스로부터 만들어진 것인지를 강조하는 보다 구체적인 의미를 갖고 있다.예를들어 ‘책상은 인스턴스이다.’보다는 ‘책상은 객체다.’라는 것보다 ‘책상은 책상클래스의 인스턴스이다.’라고 하는게 좀 더 자연스럽다.
2.3 객체의 구성요소 - 속성과 기능
객체는 다수의 속성과 다수의 기능으로 이루어져있다. 즉 객체는 속성과 기능의 집합이다. 클래스란 객체를 정의한 것이므로 클래스에는 객체의 모든 속성과 기능이 정의되어있고, 클래스로부터 객체를 생성하면 클래스에 정의된 속성과 기능을 가진 객체가 만들어진다.
- 속성(property) : 멤버변수, 특성, 필드, 상태
- 기능(funtion) : 메서드 , 함수, 행위
TV를 예를 들면 TV의 속성으로는 전원상태, 크기 , 길이, 높이, 색상, 볼륨이 있으며 기능으로는 켜기, 끄기, 볼륨높이기, 채널바꾸기 등이 있다. 즉, 객체지향 프로그래밍에서는 속성과 기능을 각각 변수와 메서드로 표현하는데 이를 코드로 표현하면 다음과 같다.
public class TV {
String color;
boolean power; //on, off 2가지
int channel;
void power(){
power = !power;
}
void channelUp(){
channel++;
}
void channelDown(){
channel--;
}
}
2.4 인스턴스의 생성과 사용
위처럼 TV클래스를 선언한 것은 설계도를 작성한 것에 불과해 TV인스턴스를 생성해야 제품(TV)를 사용할 수 있다.
Tv t; //클래스의 객체를 참조하기 위한 참조변수를 선언
t = new TV();// TV인스턴스 생성한 후 생성된 TV 인스턴스의 주소를 t에 저장
여기서 참조변수란 실제값을 저장한 변수가 아니라 값이 들어가 있는 주소를 가진 변수를 말한다.
public class TV {
String color;
boolean power; //on, off 2가지
int channel;
void power(){
power = !power;
}
void channelUp(){
channel++;
}
void channelDown(){
channel--;
}
}
class TVTest{
public static void main(String[] args) {
TV t;// 1) TV 인스턴스를 참조하기 위한 변수 t선언
t = new TV(); // 2) TV인스턴스 생성
t.channel = 7; // 3) 멤버변수 channel에 7대입
t.channelDown(); //4) 메서드 호출
System.out.println("현재 chnnel은" + t.channel + "입니다 ");
}
}
위의 코드를 더 자세히 설명하면
1) TV 클래스 타입의 참조변수 t를 선언한다. 이때 메모리에 참조변수 t를 위한 공간이 마련되고 인스턴스가 생성되지 않았으므로 참조변수로는 아무것도 할 수없다. 따라서 이 상태로 컴파일하면 에러가 뜬다.
2) 연산자 new 에 의해 TV 클래스의 인스턴스가 메모리의 빈 공간에 생성된다. 주소가 0x100인곳에 생성되었다고 가정한다면 이때 멤버변수는 각 자료형에 해당하는 기본값으로 초기화된다. 그리고 대입연산자 = 에 의해 생성된 객체의 주소값이 참조변수 t에 저장된다. 이때 참조변수 t를 통해 tv인스턴에 접근 가능하다. 이처첨 인스턴스를 다루기 위해서는 참조변수가 필요하다.
3) 참조변수 t에 저장된 주소에 있는 인스턴스의 멤버변수 channel에 7을 저장한다. 이때 멤버변수(속성)을 사용하려면 참조변수.멤버변 수 와 같이 사용할 수 있다.
4) 참조변수 t가 참조하고 있는 Tv인스턴스의 channelDown() 메소드를 호출한다. 여기서 알수 있는 점은 인스턴스는 오직 참조변수를 통해서만 다룰 수 있으며 참조변수의 타입은 인스턴스의 타입과 일치해야한다.
class TVTest {
public static void main(String[] args) {
TV t1 = new TV();
TV t2 = new TV();
t1.channel= 7;
System.out.println("t1의 채널 번호" + t1.channel);//7
System.out.println("t2의 채널 번호" + t2.channel);//0
}
}
이제 위의 Tv 클래스를 가지고 t1,t2 인스턴스를 생성했다. 그리고 인스턴스 t1의 멤버변수 channel의 값을 변경했다. 이때는 같은 클래스에서 생성되었을지라도 다른 메모리에 생성되어 각 인스턴스의 속성(멤버변수)는 다른 값을 갖는다.
class TVTest {
public static void main(String[] args) {
TV t1 = new TV();
TV t2 = new TV();
t1.channel= 7;
t2= t1; // !!
System.out.println("t1의 채널 번호" + t1.channel); //7
System.out.println("t2의 채널 번호" + t2.channel); //7
}
}
만약에 t1이 저장하고 있는 값(주소)를 t2에 저장하면 어떻게될까? 이때 t2가 기존에 가지고 있는 주소값은 사라지고 t1에 저장되어 있는 주소값이 t애 저장되게 된다. 따라서 t2는 t1이 참조하고 있는 인스턴스를 같이 참조하게 되고 t2가 원래 참조하고 있던 인스턴스는 GC에 의해 메모리에서 제거된다.
2.5 객체 배열
많은 수의 객체를 다워야할 때, 객체를 배열로 다루면 편리할 것이다. 이를 객체 배열이라고 한다. 객체배열안에 객체가 저장되는 것은 아니고 객체의 주소가 저장된다. 즉 객체 배열은 참조변수들을 하나로 묶는 참조변수배열인 것이다.
TV tv1,tv2,tv2; //X
TV[] tvArr = new Tv[3]; //객체 배열 생성 후 각 요소에 저장
tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();
객체배열을 사용할때 중요한 것은 객체배열을 생성한 것은 그저 객체를 다루기 위해 참조변수들이 만들어진 것 뿐 객체가 저장되지 않았다. 따라서 객체를 생성해 객체배열의 각 요소에 저장하는 것을 잊으면 안 된다.
2.6 클래스의 또 다른 정의
지금까지 설명한 클래스는 객체를 생성하기 위한 틀이며 클래스는 속성과 기능으로 정의되어있다 라는 설명은 모두 객체지향이론의 관점에서 내린 정의이다. 프로그래밍 관점에서의 클래스의 정의는 또 다르다.
클래스
1. 데이터와 함수의 결합
변수 → 배열 → 구조체(서로 관련된 데이터를 종류에 관계없이 하나의 집합으로 저장) → 클래스(데이터와 함수의 결합) 와 같이 데이터 저장형태는 발전해왔다. 따라서 자바에서는 변수(데이터)와 함수를 하나의 클래스에 정의해 서로 관계가 깊은 변수와 함수들을 같이 다룰 수 있다. 예를들어 String클래스 내부에서는 문자형 배열이 선언되어있고 문자열을 다루는데 필요한 함수들이 함께 정의되어있다.
2. 사용자 정의 타입 (user- defined type)
언어에서 제공하는 자료형외에 프로그래머가 관련된 변수를 묶어서 하나의 타입으로 새로 추가하는 것을 사용자 정의 타입이라고 하며, 클래스가 곧 사용자 정의타입이다. 따라서 기본형의 개수는 8개이고 참조형의 개수는 정해져있지 않은 이유가 프로그래머가 새로운 타입을 추가할수있기때문이다.
출처 : 자바의 정석
'Java' 카테고리의 다른 글
[JAVA] 자바의 hashcode는 무엇이고, 어디에 사용할까? (0) | 2024.01.18 |
---|---|
[JAVA] == 와 equals()의 차이 (1) | 2024.01.05 |
[JAVA] 형변환(캐스팅, casting) (0) | 2023.12.17 |
[JAVA] 기본형 변수(primitive type) (0) | 2023.12.15 |
[JAVA] 진법과 2의 보수법 (1) | 2023.12.07 |