객체지향 언어란 프로그램을 다수의 객체로 만들고, 이 객체끼리 서로 상호작용하도록 만드는 프로그래밍 언어이다.
여기서 객체란, 현실로 따지면 TV, 책, 냉장고, 컴퓨터, 카메라 등이 모두 객체인 것이다.
위의 그림에 있는 물건들 처럼 객체는 객체마다 고유한 특성과 행동을 가진다.
캡슐화의 가장 큰 장점은 정보은닉에 있다.
캡슐화는 말 그대로 객체를 캡슐로 싸서 내부를 볼 수 없게 하는 것이다.
캡슐화는 객체의 속성을 보호하기 위해 사용되며 외부의 접근으로부터 객체를 보호해 줌으로써 데이터와 코드의 형태를 외부에서 알 수 없다는 장점이 있다.
Method를 설계할 때 속성이 선언되었으나, 이 속성의 상태를 변경하는 Method가 없다면 잘못 선언된 속성이다.(일반적으로 getter/setter)
실물 객체가 가진 기능을 모두 제공해야 하고 각각의 Method는 서로 관련성이 있어야 한다.
객체 안의 Method는 객체 안의 속성을 처리해야 하며, 다른 객체를 전달받아 해당 다른 객체에 정의된 속성을 직접 처리하면 안 된다.
단, Method에 실행에 필요한 값들은 객체의 형태가 아닌 매개변수의 형태로 전달돼야 한다.
public class Member {
// 속성 선언
private String id;
private String password;
// 속성의 상태를 변경하거나 가져오는 getter/setter 메서드
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Getter/Setter : 외부에서 내부 속성에 직접 접근하는 것이 아닌 Getter/Setter Method를 통해서 접근하도록 적용해 줌.
그리고 캡슐화가 적용된 유명한 메서드들은 다음과 같다
메서드명 | 역활 |
---|---|
CRUD Method | 데이터 처리를 위한 기본적인 CRUD Method를 제공 |
Business Logic Method | 비즈니스 로직 처리를 위한 Method를 제공 |
객체의 생명 주기 처리 Method | 흔히 destroy(), disconnect() 등 quit() 등 소멸에 대한 Method |
객체의 영구성 관리 Method | 영구성(유효성) 속성에 대한 변경이 필요한 경우 외부에서는 접근이 불가능하도록 private로 선언하며, 내부의 다른 Method를 통해서 사용 되도록 한다. |
Method의 속성은 반드시 1개에 속할 필요는 없으며, 여러 속성에 해당될 수 있다.
객체지향의 패러다임 중 하나인 추상화를 제공한다.
보통의 캡슐화 코딩이라고 하면 주로 변수는 private로 선언하고, Method를 public으로 선언하는 형태를 많이 가지게 되는데 이는 객체의 무결성을 위함이다.
캡슐화 코딩에서는 Getter/Setter를 제외하고는 public method는 입력된 매개변수를 Validation을 한 후에 실행하는 것을 기본으로 한다.
Validation을 통하여 객체의 값을 바꾸거나, 값에 대한 유효성을 가질 수 있다.
객체지향에서의 상속은 속성의 상속이 아닌, 하위로 내려갈수록 구체화되는 것이다.
상위 객체의 속성이 하위 객체에 물려지고 하위 객체가 상위 객체의 속성을 모두 가지는 관계이다.
Java는 클래스의 다중 상속이 불가능하지만 인터페이스 다중 상속은 가능하다.
인터페이스 두개를 Human 클래스에 다중상속받기.
public interface Eat {
void eatPrint();
}
public interface Move {
void movePrint();
}
Eat 과 Move 인터페이스 다중상속 받기
public class Human implements Eat, Move {
// 필드 선언
protected String name;
@Override
public void eatPrint() {
System.out.println(name + "가 먹는다");
}
@Override
public void movePrint() {
System.out.println(name + "가 움직인다");
}
}
Human 을 상속받아 Human이 상속받은 두 인터페이스 사용해보기
public class Main extends Human{
// Human 을 상속받아서 가능한 생성자
Main(String name){
// Human 에 name 필드를 상속받아 매개변수 name 입력받고 넣어주기
this.name = name;
}
public static void main(String[] args) {
// main 이름의 인스턴스 생성
Main main = new Main("잠만보");
// Human에서 상속받은 두 인터페이스 다 사용해보기.
main.eatPrint();
main.movePrint();
}
}
결과
잠만보가 먹는다
잠만보가 움직인다
최상위 클래스의 구조를 보고, 하위 클래스의 동작을 이해할 수 있다.
상속을 이용하여, 해당 클래스에 필요한 속성 및 메서드를 모두 정의하지 않고, 상속을 받아서 사용할 수 있다.
일관된 형태의 클래스 객체를 추가할 수 있어, 간단하게 프로그램 확장이 가능하다.
각 객체마다, 자신의 메서드를 정의하고 있다면, 코드 수정에서 많은 작업이 필요하지만, 상속을 사용한 경우 일관된 형태로 작성이 가능하다.
다형성은 하나의 개체가 여러 개의 형태로 변화하는 것을 말하며, 이를 객체지향에서도 유사하게 사용하고 있다.
상속과 연관된 개념으로, 같은 이름의 메서드나 클래스가 객체에 따라 다르게 동작하도록 구현한 것이다.
다시 말해, 하나의 객체가 다른 여러 객체로 재구성되는 것이다.
다형성을 하기 위해서는 오버 로딩(Overloading), 오버라이딩(Overriding)을 통해서 사용 가능하다.
객체지향에서의 추상화는 모델링이다.
객체들의 공통된 특징(기능, 속성)을 도출하는 것이며, 클래스를 정의하는 것을 추상화라고 할 수 있다.
구체적으로 공통적인 부분, 또는 특정 특성을 분리해서 재조합 하는 부분이 추상화이고 다형성, 상속 모두 추상화에 속한다.
추상화 클래스 예제)
public abstract class Animal {
// 동물의 이름과 울음소리를 받는다.
protected String name;
protected String speak;
// 동물의 이름을 매개변수로 받는 생성자
public Animal(String name) {
this.name = name;
}
// 추상화 메서드 제공(상속받는 클래스들은 무조건 오버라이드 해서 구현해야함!)
abstract void speaking();
}
class Cat extends Animal{
public Cat(String name) {
super(name);
this.speak = "야옹";
}
@Override
void speaking() {
System.out.println("안뇽 나는 " + this.name + "이다옹 " + this.speak + "~!~");
}
}
class Tiger extends Animal{
public Tiger(String name) {
super(name);
this.speak = "어흥";
}
@Override
void speaking() {
System.out.println("안녕하세요 저는 " + this.name + "입니다. " + this.speak + "!!!");
}
}
실행문
public class MainAnimal {
public static void main(String[] args) {
Tiger tiger = new Tiger("호랑이");
Cat cat = new Cat("고양이");
tiger.speaking();
cat.speaking();
}
}
결과문
안녕하세요 저는 호랑이입니다. 어흥!!!
안뇽 나는 고양이이다옹 야옹~!~
추상화를 통해 잘 설계하면 여러 클래스를 정의했을 때 중복코드가 줄어들고 코드의 재사용성이 향상된다.
앞선 이유로 인하여, 유지 보수의 효율성이 향상된다.