현실 세계에서 어떠한 제품을 만들기 위해 부품들을 하나씩 조립해서 완성시키는 것처럼 소프트웨어 또한 필요한 부품들을 만들고 하나씩 조립해서 하나의 완성된 프로그램을 만들 수 있는데 이러한 기법을
객체지향 프로그래밍
이라고 부릅니다.
- 세상에 존재하는 물체를 뜻하며 식별이 가능한 것을 의미
- 물리적으로 존재하는 자동차, 도서관, 계산기 ...
- 개념적이지만 식별이 가능한 강의, 운동, 배달 ...
- 객체가 가진 고유한 특성인 속성(필드)과 객체의 행동 패턴인 행위(메소드)로 구성
- 속성 : 자동차의 회사, 모델, 색상, 가격 ...
- 행위 : 가속, 브레이크, 변속, 조명 ...
- 현실에서 사람과 자동차는 서로 행위를 통해 상호작용
- 사람이 가속 페달을 밟으면 자동차는 속도를 올리며 이동
- 사람이 브레이크 페달을 밟으면 자동차는 속도를 줄이며 정지
- Java에서는 행위를 나타내는 메소드를 통해 상호작용
- 메소드를 통해 데이터를 주고 받을 수 있음
- 메소드를 호출할 때 괄호 안에 데이터를 넣을 수 있는데 이 때 이 데이터를 파라미터라고 칭함
- 사용 관계
- 사람 객체는 자동차 객체를 사용
- 포함 관계
- 타이어, 문, 핸들 객체는 자동차 객체에 포함
- 상속 관계
- 만약 같은 공장에서 자동차와 기차가 생산된다고 가정한다면, 공통된 기계 시스템 객체를 토대로 만들어지기에 자동차, 기차 객체와 기계 시스템 객체는 상속 관계가 성립됨
- 캡슐화
- 속성(필드)과 행위(메소드)를 하나로 묶어 객체로 만든 후 내부 구현 내용은 외부에서 알 수 없게 감추는 것
- 외부 객체에서 해당 필드와 메소드를 잘못 사용하여 객체가 변화하지 않게 하는 것이 목적
- 상속
- 부모 객체가 가지고 있는 필드와 메소드를 자식 객체에 물려주어 자식 객체가 이를 사용할 수 있는 것
- 각각의 객체들을 상속 관계로 묶음으로서 객체 간의 구조를 파악하기 쉬움
- 필드와 메소드를 변경하는 경우, 부모 객체만 수정해도 모든 자식 객체에 반영이 되기 때문에 일관성을 유지가 쉬움
- 부모 객체의 필드와 메소드를 사용할 수 있기 때문에 코드의 중복은 감소하며 재사용성은 증가
- 다형성
- 객체가 연산을 수행할 때, 하나의 행위에 대해 각 객체가 가지고 있는 고유한 특성에 따라 여러 가지 형태로 재구성되는 것
- 추상화
- 객체에서 공통된 부분들을 모아 상위 개념으로 새롭게 선언하는 것
- 자동차는 설계도를 토대로 생산됨
- Java에서도 객체를 만들기 위해 설계도에 해당하는 클래스가 필요
- 클래스를 토대로 생성된 객체를 해당 클래스의 인스턴스라고 부르며, 이 과정을 인스턴스화라고 칭함
- 동일한 클래스로 여러 개의 인스턴스를 생성할 수 있음
- 클래스는 객체를 생성하기 위한 설계도로서 필드, 생성자, 메소드로 구성됨
- 클래스를 만들기 위해선 아래의 4가지 단계가 필요
- 만들려고 하는 설계도 선언(클래스 선언)
- 객체가 가지고 있어야 할 속성(필드) 정의
- 객체를 생성하는 방식을 정의(생성자)
- 객체가 가지고 있어야 할 행위(메소드) 정의
// <클래스 선언>
public class Car {
// <필드 정의>
String company; // 자동차 회사
String model; // 자동차 모델
String color; // 자동차 색상
double price; // 자동차 가격
double speed; // 자동차 속도 , km/h
char gear; // 기어의 상태, P,R,N,D
boolean lights; // 자동차 조명의 상태
// <생성자 정의>
// 자동차 객체의 생성 방식을 선언
// 반환 타입이 없고 이름은 클래스의 이름과 동일
// 괄호 안에 아무 것도 없는 것을 기본 생성자라 칭함
public Car() {} // 기본 생성자
// <메소드 정의>
// 매개변수인 kmh를 통해 speed 필드에 해당 값을 저장하고 반환
double gasPedal(double kmh) {
speed = kmh;
return speed;
}
// speed 필드의 값을 0으로 바꾸고 저장
double brakePedal() {
speed = 0;
return speed;
}
// 매개변수인 type를 통해 gear 필드에 해당 값을 저장하고 반환
char changeGear(char type) {
gear = type;
return gear;
}
// lights의 현재 논리값을 반전 시키고 반환
boolean onOffLights() {
lights = !lights;
return lights;
}
// "빵빵"을 출력
void horn() {
System.out.println("빵빵");
}
}
- 객체 생성
- 객체 생성 연산자인
new
를 사용하여 클래스로부터 객체를 생성- 기본 생성자의 형태와 같기 때문에 new 연산자에 의해 객체가 생성되면서 기본 생성자가 호출됨
new Car(); // Car클래스 객체 생성
- 참조형 변수
- 객체가 생성되면 해당 인스턴스의 주소가 반환되기 때문에 해당 클래스의 참조형 변수를 사용
Car car1 = new Car(); // Car클래스의 객체인 car1 인스턴스 생성 Car car2 = new Car(); // Car클래스의 객체인 car2 인스턴스 생성
- 객체 배열
- 객체는 참조형 변수와 동일하게 취급되기 때문에 배열 및 컬렉션으로 저장, 관리 가능
public class Main { public static void main(String[] args) { Car[] carArray = new Car[3]; Car car1 = new Car(); car1.changeGear('P'); carArray[0] = car1; Car car2 = new Car(); car2.changeGear('N'); carArray[1] = car2; Car car3 = new Car(); car3.changeGear('D'); carArray[2] = car3; for (Car car : carArray) { System.out.println("car.gear = " + car.gear); //car.gear = P //car.gear = N //car.gear = D } } }