1. 캡슐화
캡슐화(encapsulation)이란, 추상화의 한 종류로 객체의 속성과 메서드를 묶고,
필요한 부분만 외부에 공개하는 방식으로
불필요하게 노출될 필요가 없는 내부 구현 정보를 숨기는 것이다
예시 코드로, 제 지갑을 소개합니다.
총 금액을 알려주는 기능과, 돈을 지불하는 기능을 갖추고 있습니다.
public class Wallet {
private int money;
public Wallet(int money){
this.money = money;
}
public int getTotalMoney(int price) {
return this.money;
}
private void substractMoney(int charge) {
money -= charge;
}
}
자바에서 캡슐화를 가능하게 하는 방법으로 접근 제어자를 이용한다.
attribute에 해당하는 부분은 private으로 설정하고,
생성자를 이용하여 지갑의 돈을 초기화하고, setter와 getter만 public으로 두어 외부에서 메서드를 활용하지 않으면 내부 상태를 제어할 수 없게 만든다.
2. 추상화
추상화란, 불필요한 중복을 제거하고 공통적인 속성과 기능을 추출하여 정의하는 것입니다.
이를 통해 변경에 더욱 유연한 코드를 만들 수 있는데요,
카페의 메뉴판을 가정하고 코드를 작성했습니다.
카페에는 메뉴가 아시다시피 정말 많은데요, 만약에 메뉴가 하나씩 추가된다면 수많은 클래스가 생겨날 것입니다.
하지만, 이러한 메뉴에는 공통적인 특성이 있습니다! 바로 메뉴 정보를 보여주어야 한다는 점인데요.
이러한 공통적인 속성이나 기능을 한데 묶어 Menu 라는 추상클래스로 정의한다면,
어떠한 메뉴가 추가되어도 Menu의 메서드만 override하여 구현하면 되겠죠?
또한 비슷한 메뉴이더라도, 내부적으로 구현해야 하는 부분은 다를 수 있습니다.
그래서 공통적인 부분만 추상화하고, 세부적인 구현에 대한 책임은 하위 클래스에게 미뤄 두는 것이죠.
public abstract class Menu {
void showMenu(){}
}
class Coffee extends Menu {
private String name;
private int price;
@Override
void showMenu() {
System.out.println(name);
System.out.println(price);
}
}
class Latte extends Menu {
private String name;
private int price;
@Override
void showMenu() {
System.out.println(name);
System.out.println(price);
}
}
class Juice extends Menu {
private String name;
private int price;
@Override
void showMenu() {
System.out.println(name);
System.out.println(price);
}
}
3. 다형성
다형성이란, 어떤 객체의 속성이나 기능이 상황에 따라서 여러 가지 형태를 지닐 수 있는 속성을 의미합니다.
당장 저의 경우만 하더라도, 학교에서는 학생이며, 가족에서는 첫째, 학회에서는 운영진 등 상황에 따라 각기 다른 역할과 특성을 지니고 있습니다.
이를 구현하기 위해 메서드 오버라이딩과 오버로딩을 사용합니다.
먼저 오버로딩이란, 같은 클래스 내에서 거의 동일한 기능을 하지만, 파라미터의 개수나 타입이 다른 경우에
그 메서드 네이밍을 해당 메서드의 이름과 동일하게 하도록 허용해 주는 것을 의미합니다.
public int add(int number1, int number2) {
return number1 + number2;
}
어떤 두 수를 합해주는 코드가 있다고 생각해봅시다. 만약 우리가 세 수를 더하는 함수를 만들고 싶다면 어떻게 해야 할까요..? 또 새로운 메서드를 정의해야합니다.
public int add(int number1, int number2) {
return number1 + number2;
}
public int addForThree(int number1, int number2, int number3) {
return number1 + number2 + number3;
}
그런데, 만약 네 수를 더하고 싶다면요..? 이때마다 메서드 네이밍을 새롭게 할 수도 없는 노릇입니다.
따라서 java에서는 오버로딩이라는 속성을 통해 메서드 네이밍을 동일하게 하는 것을 허락합니다.
public int add(int number1, int number2) {
return number1 + number2;
}
public int add(int number1, int number2, int number3) {
return number1 + number2 + number3;
}
오버라이딩이란, 참조하는 클래스의 메서드를 맥락에 맞게 재정의하여 사용하는 것입니다.
즉 메서드의 이름은 같으나, 상황에 따라서 다른 역할을 수행합니다.
class Parent {
void display() { System.out.println("부모 클래스의 display() 메소드입니다."); }
}
class Child extends Parent {
// 오버라이딩된 display() 메소드
void display() { System.out.println("자식 클래스의 display() 메소드입니다."); }
void display(String str) { System.out.println(str); } // 오버로딩된 display() 메소드
}
이를 통해 하나의 타입을 이용하여 상속 관계에 있는 다른 type의 객체를 참조할 수 있습니다.
4. 상속
자바에서 상속이란 기존의 클래스를 재활용하여 새로운 클래스를 작성하는 자바의 문법 요소이다.
상속은 상위 클래스와 하위 클래스로 나누어 상위 클래스의 멤버(필드, 메서드, 이너 클래스)를 하위 클래스와 공유하는 것을 의미한다.
이를 통해 중복되는 코드를 줄이고, 서로 상속 관계에 있는 클래스의 기능을 자유롭게 이용할 수 있다는 점이 장점입니다.
class Person {
String name;
int age;
void learn() {
System.out.println("공부하기");
}
void walk() {
System.out.println("걷기");
}
void eat() {
System.out.println("식사하기");
}
}
class Programmer extends Person {
void coding() {
System.out.println("코딩하기");
}
}
하지만, 상속을 이용할 경우 단점도 있습니다.
이는 각 클래스들끼리 강하게 결합되어 결합도를 높이기 때문인데요, 상속을 이용하면 불필요한 속성들과 기능까지도 함께 상속받기 때문입니다.
출처
'CS > Java' 카테고리의 다른 글
[Java] Garbage Collection(GC)의 동작 원리 (0) | 2024.06.24 |
---|---|
Java의 Collections Deep Dive - 1 : HashMap이란? (0) | 2024.05.17 |
@Override가 뭐야? (0) | 2023.03.29 |
[자바] 인터페이스는 객체지향의 4대 특성중에 무엇을 지니는가? (1) | 2023.03.28 |