내가 생각하는 캡슐화는 하나의 어떤 로직, 데이터를 클래스 또는 객체로 묶어서 데이터의 손상을 방지하거나 정해진 규칙이나 로직에 따라서만 사용 가능하게 만드는 방식이다.
예를 들어 VO(Variable Object) 등의 패턴을 사용할 때 사용된다.
접근제어자의 이해가 필요하다.
// 코드 예시)
import java.time.LocalDate;
public class Main {
public static void main(String[] args) {
Student student = new Student("김송아", 20);
System.out.println("학생성명 : " + student.getName());
System.out.println("출생년도 : " + student.getBornYear());
}
}
class Student {
// 접근제어자로 외부로부터 데이터를 숨김
private String name;
private int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName(){
// 공백을 포함하는 규칙을 포함
return String.join(" ", name.split(""));
}
public int getBornYear() {
// 출생년도를 구하는 로직을 포함
return LocalDate.now().getYear() - age;
}
}
공통적인 요소를 선별하고 정의하여 필수요소누락, 추가 등의 부분에서 실수를 방지한다.
전체적인 틀을 모델링하는 설계도와 비슷한 개념이다.
public interface IAnimal {
// 구현해야할 메소드들
void setName(String name);
String getName();
void setGender(String gender);
void setSound(String sound);
void sounds();
}
/*
IAnimal 인터페이스를 구현한다면
위 5개의 정의된 메소드를 모두 구현해야한다.
*/
public class lamb implements IAnimal {
String name;
String gender;
String sound;
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public void setGender(String gender) {
this.gender = gender;
}
@Override
public void setSound(String sound) {
this.sound = sound;
}
@Override
public void sounds() {
System.out.println(this.sound);
}
}
객체는 캐스팅해서 여러 타입의 형태를 가질 수 있다. ex) 한국은 국가이다.
하지만 모든 국가가 한국이 아니듯이 객체 간의 관계를 제대로 파악, 설계하는 것이 중요하다.
제네릭 와일드카드 구현할 때 이 개념을 모르면 캐스팅해서 파라미터를 넘길 때 얼탈 수도 있다. 참고
public class Country {
public String hello() {
return "shake hands";
}
}
class Korea extends Country {
@Override
public String hello() {
return "안녕하세요~";
}
}
class Japan extends Country {
@Override
public String hello() {
return "곤니찌와~";
}
}
위와 같은 관계가 있다고 할 때
public class Main {
public static void sayHello(Country country){
System.out.println(country.hello());
}
public static void main(String[] args) {
sayHello(new Country());
sayHello(new Korea());
sayHello(new Japan());
}
}
출력결과)
shake hands
안녕하세요~
곤니찌와~
sayHello
의 Country
파라미터는 Korea
, Japan
등의 상속받는 다양한 타입으로 변환될 수 있다.
다형성을 잘 알고있으면 sayHello
메소드처럼 재사용성이 높아지게 코드를 작성할 수 있다.
부모의 특징을 유전받는다고 생각하면 편하다.
extends
키워드로 어떤 클래스를 상속받은 클래스라면,
상속하는(부모) 클래스의 메소드, 필드 등도 상속받는(자식)클래스에서도 사용이 가능하다.
부모와 자식 관계로 생각하면 편한 이유는 부모가 서로 눈 색깔이 다르다고 하면, 오드아이가 아니라면 자식은 둘중 하나의 색깔을 유전받기 때문에 extends
키워드를 사용한다면 두개 이상의 클래스를 상속 받을 수 없다는 개념과 이어지기 때문이다. (implements는 가능)
// 부모클래스
public class Mom {
String eyes = "blue";
public String hobby() {
return "gamble";
}
}
// 자식클래스
public class Son extends Mom {
public String getEyesColor() {
return eyes;
}
}
public class Main {
public static void main(String[] args) {
Son son = new Son();
System.out.println(son.getEyesColor()); // blue출력
System.out.println(son.hobby()); // gamble출력
}
}
Son
클래스에서 eyes
나 hobby()
메소드를 구현하지 않아도 사용할 수 있어서 중복된 코드를 방지할 수 있고 나중에 수정할 때도 Mom
클래스만 코드만 수정할 수 있어서 유지보수성 또한 높아진다.