- 객체 지향 프로그래밍 = 실제 세계를 컴퓨터 속에 옮겨 놓기
- 실제 사물의 속성과 기능을 분석
- 데이터(변수)와 함수로 정의
- 필요한 사물끼리 연결
실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 모든 사건들은 사물간의 상호작용이다.
- OOP (상속, 캡슐화, 추상화, 다형성) 개념을 중심으로 점차 구체적으로 발전되었다
- 기존의 프로그래밍 언어(절차적)에 몇 가지 새로운 규칙을 추가한 언어
- 코드의 재사용성이 높고 유지보수가 용이, 중복 코드 제거할 수 있는 특징이 있다
- 코드의 재사용성이 높다
- 새로운 코드를 작성할 때 기존의 코드를 이용하여 쉽게 작성할 수 있다
- 코드의 관리가 용이하다
- 코드간의 관계를 이용해서 적은 노력으로 쉽게 코드를 변경할 수 있다
- 신뢰성이 높은 프로그래밍을 가능하게 한다
- 제어자, 메서드를 이용하여 데이터를 보호하고 올바른 값을 유지하도록 한다
- 코드의 중복을 제거하여 코드의 불일치로 인한 오동작을 방지한다
객체 지향 프로그래밍의 4대 특징을 간단하게 알아보겠다 (추후 하나씩 자세히 다룰 예정)
- 데이터와 데이터를 활용하는 함수를 캡슐(Class) 안에 두는 것
- 즉 개념 혹은 논리적으로 연관된 데이터와 함수를 캡슐화 한다
- 클래스 안에서는 표시할 속성(public 변수)와 숨길 속성(private 변수)을 선택할 수 있음
특징 | 설명 |
---|---|
데이터 캡슐화 | 필드와 메서드를 하나로 묶는 것 |
은닉화 | 외부에 드러나게 하지 않기를 원하는 데이터를 감추어(private) 외부에서 데이터를 직접 접근하는 것을 방지 |
class TV {
int channel;
// 가격은 getPrice()를 통해서만 가져갈 수 있다 -> 직접 접근 불가
private int price;
String color;
void channelUp() {
this.channel++;
}
public int getPrice() {
return price;
}
public void setColor(String color) {
this.color = color;
}
}
- 부모클래스의 특징과 기능을 자식클래스에게 물려주는 것
- 코드를 더 작은 단위로 Class를 쪼개면서 재사용을 할 수 있다
- 공통적인 요소를 합쳐 중복 코드를 제거한다
- 부모클래스 수정 시 모든 자식클래스도 일괄 수정된다
class Entrepreneur {
String firstName;
String lastName;
private int shares;
private String company;
}
class Actor {
String firstName;
String lastName;
private int oscars;
private int age;
}
// firstName과 lastName이 공통적으로 사용되는 멤버이다 -> 상속
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
class Person {
String firstName;
String lastName;
}
class Entrepreneur extends Person {
private int shares;
private String company;
}
class Actor extends Person {
private int oscars;
private int age;
}
- 구현 세부 정보를 숨기는 일반 인터페이스를 지정하는 행위
- 세부 사항의 수정이 일어나도 해당 메서드를 사용하는 다른 어느 곳이든 수정을 할 필요가 없다
💡 예시를 들어보자
자동차에는 엑셀, 브레이크, 핸들, 버튼 등 다양한 인터페이스가 존재한다
우리는 아래와 같이 알 수 있다
엑셀: 차가 움직인다
브레이크: 차가 멈춘다
핸들: 차의 방향을 조절한다
버튼: 각각의 기능이 있다
하지만 구현 세부정보는 각 제조사마다 다르지만 우리는 몰라도 차를 운전하는데 전혀 지장이 없다.
따라서 인터페이스는 구현체 내부에서 어떻게 돌아가는지 몰라도 원하는 기능을 사용하는데 문제가 없다는 특징이 있다
- 여러개의 형태를 갖고있는 것
- 즉 변수 혹은 메서드가 상황에 따라 다른 결과가 나온다
- 오버로딩과 오버라이딩을 통해 가능하다
- 메서드가 어떻게 작동해야되는지에 대한 최소한의 규칙이 정해져있다 (return 타입 등)
- 메서드의 핵심은 보존하면서 구현방식의 모양과 모습만 다르게 구현함
class Person {
public String sayHi() {
return "ㅎㅇ";
}
public String sayBye() {
return "ㅂㅂ";
}
}
class 한국인 extends Person {
}
class Italian extends Person {
@Override
public String sayHi() { // 오버라이딩
return "Hi!";
}
}
public static void main(String[] args) {
한국인 한국인1 = new 한국인();
한국인1.sayHi(); // 출력값: ㅎㅇ
Italian italian1 = new Italian();
italian1.sayHi(); // 출력값: Hi!
}
- 객체는 ‘실제로 존재하는 것’ 으로써 우리 주변에서 볼 수 있는 모든 사물들이 곧 객체이다
- 개념이나 논리 같은 무형적인 것들도 포함
프로그래밍 관점 → 클래스에 정의된 내용대로 메모리에 생성
- 객체 = 속성(변수) + 기능(메서드)
객체 | 설명 |
---|---|
객체의 정의 | 실제로 존재하는 것, 사물 또는 개념 |
객체의 용도 | 객체가 가지고 있는 기능과 속성에 따라 다름 |
유형의 객체 | 책상, 의자, 모니터 등과 같은 사물 |
무형의 객체 | 수학공식, 프로그램 에러와 같은 논리나 개념 |
- 객체를 정의해놓은것 → 객체의 설계도 또는 틀이라고 정의
객체 | 클래스 |
---|---|
제품 | 제품 설계도 |
TV | TV 설계도 |
붕어빵 | 붕어빵 기계 |
-
클래스는 객체를 생성하는데 사용된다
자동차라는 객체가 필요하다고 가정하자
프로그래밍에서는 클래스를 먼저 작성한 후, 클래스로부터 객체를 생성하여 사용해야 한다!
-
자동차라는 클래스를 작성한다 (설계도)
class Car { .... }
-
자동차라는 클래스를 통해 객체를 생성한다 (인스턴스화)
Car car= new Car();
-
서로 관련된 변수들을 정의하고 이들에 대한 작업을 수행하는 함수들을 함께 정의한 것이다
-
클래스가 곧 사용자 정의 타입이다 (기본 자료형 외) - (ex. VO, DTO)
-
객체와 인스턴스는 같은 의미이다! -> 따라서 문맥에 따라 구별하여 사용하면 된다
💡 예시를 들어보자 차 인스턴스다 x -> 차 객체다 o 차는 차 클래스의 객체이다 x -> 차는 차 클래스의 인스턴스이다 O
-
클래스 —— (인스턴스화) ——> 인스턴스(객체)
- 클래스로부터 객체를 만드는 과정 → 클래스의 인스턴스화
- A 클래스로부터 만들어진 객체 → A 클래스의 인스턴스
// 클래스의 객체를 생성 -> 객체의 주소를 참조변수에 저장 클래스명 변수명 = new 클래스명(); Class Human { ... } // new를 통해 Human 인스턴스 생성 -> gibeom이라는 참조변수에 Human 인스턴스의 주소 저장 Human gibeom = new Human();
-
인스턴스는 오직 참조변수를 통해서만 다룰 수 있고, 참조변수의 타입과 인스턴스의 타입은 일치해야 한다
-
하나의 인스턴스를 여러개의 참조변수가 가르키는 경우 → 가능
Human gibeom1 = new Human(); Human gibeom2 = new Human(); gibeom1 = gibeom2 // 참조변수 gibeom1한테 gibeom2의 주소값을 부여 // gibeom1의 본래 주소값은 garbage collector에 의해 메모리 반환
-
여러 인스턴스를 하나의 참조변수가 가르키는 경우 → 불가능
- 위 예시의 gibeom1 처럼 덮어씌워짐
- 객체는 속성과 기능의 집합
- 객체가 가지고 있는 속성과 기능을 그 객체의 멤버(구성원, member)라고 한다
구성 요소 | 설명 |
---|---|
속성 (property) | 멤버변수, 특성(attribute), 필드(field), 상태(state) |
기능 (function) | 메서드, 함수, 행위(behavior) |
- 속성과 기능에 대한 예시 (TV)
속성 | 기능 |
---|---|
크기, 길이, 높이, 무게, 색상, 볼륨, 채널 등 | 켜기, 끄기, 볼륨 높이기 낮추기, 채널 변경하기 등 |
채널 → int channel; | 채널 변경하기 → channelUp() { … } |
-
같은 클래스로부터 생성되었을지라도, 각 인스턴스의 속성(멤버변수)은 서로 다른 값을 유지 → 서로 다른 주소값을 참조
-
메서드의 내용은 모든 인스턴스에 대해 동일
Class Human { String gender; int age; void increaseAge() { ++age; } } Class HumanTest { Human gibeom = new Human(); Human beom = new Human(); gibeom.increaseAge() // 속성중에 하나인 멤버변수 age는 각 인스턴스마다 서로 다른 값을 유지 // 하지만 increaseAge 같은 메서드 동작 자체는 모든 인스턴스에서 동일하게 작동 System.out.println(gibeom.age); // 1 System.out.println(beom.age); // 0 }
-
객체의 주소를 배열에 저장 → 즉 참조 변수들을 하나로 묵은 참조 변수의 배열
Human[] humanArr = {new Human(), new Human(), new Human()}