instanceof 함수란?
인스턴스.. 인스턴스.. 평소 인스턴스라는 말을 자주 들어보았다. 인스턴스란 무엇인가?
Java에서 인스턴스란 클래스를 기반으로 생성된 객체(Object)를 의미한다.
즉, 클래스는 객체를 만들기 위한 설계도이고, 인스턴스는 그 설계도를 바탕으로 실제 메모리에 존재하는 객체이다.
instanceof 연산자는 인스턴스(객체)가 해당 클래스의 인스턴스인지를 판단하는 연산자이다.
A가 B의 인스턴스인지를 판단할 때에는 ‘A instanceof B’로 사용할 수 있다.
A가 B의 인스턴스라면 true, 아니라면 false로 boolean형으로 반환한다.
instanceof 사용 예제
[예시 코드 1]
public class Cat extends Animal {
public void moveToCatTower() {
System.out.println("고양이가 캣타워로 이동");
}
}
[예시 코드 2]
public static void main(String[] args) {
Cat cat = new Cat();
action(cat);
}
private static void action(Animal animal) {
//객체에 맞는 다운캐스팅이 필요함.
if(animal instanceof Cat cat) {
cat.moveToCatTower();
}
}
[실행 결과]
고양이가 캣타워로 이동
위의 소스를 살펴보면,
Cat 클래스는 Animal클래스를 상속받았다.
action() 메서드의 매개변수는 Animal클래스이며,
‘instanceof’ 함수를 통하여 매개변수로 Cat 클래스일 경우 ‘moveToCatTower()’의 메서드가 실행되도록 되어있다.
즉, ‘instanceof’ 함수로 animal이 Cat의 인스턴스인지 아닌지를 판단할 수 있다.
이처럼, 상속 관계일 때 instanceof 함수를 효과적으로 사용할 수 있다.
하지만, instanceof 사용하면 안 되는 이유?
객체 지향 설계에서 지켜줘야 할 5개의 소프트웨어 개발 원칙이 있다.
SOLID 설계 원칙으로 칭하며, 해당 설계 원칙을 적용하면, 코드를 확장 및 유지 보수 관리가 용이해지며, 불필요한 복잡성을 제거해 리팩토링에 소요되는 시간을 줄일 수 있다. 즉, 프로젝트 개발의 생상선을 높일 수 있다는 것이다.
- SRP(Single Responsibility Principle) : 단일 책임 원칙
- OCP(Open Closed Priciple) : 개방 폐쇄 원칙
- LSP(Listov Substitution Priciple) 리스코프 치환 원칙
- ISP(Interface Segregation Priciple) : 인터페이스 분리 원칙
- DIP(Dependency Inversion Priciple) : 의존 역전 원칙
instanceof를 사용한다면..
1. ‘OCP - 개방 폐쇄 원칙’이 위배가 된다.
※ 개방 폐쇄 원칙이란? ‘확장에 열려있어야 하며, 수정에는 닫혀있어야 한다.’
private static void action(Animal animal) {
if(animal instanceof Cat cat) {
cat.moveToCatTower();
}
}
Dog라는 새로운 객체가 생겼다고 가정해 보자.
해당 action 메서드에 Dog의 instanceof 로직 코드를 추가해야 된다.
현재 ‘Dog’만 추가를 하였지만, 약 100개 종의 넘는 동물이 추가된다고 하면 animal의 instanceof 로직을 추가해야 된다.
객체의 확장에는 열려있고, 닫혀있도록 해야 되는 OCP의 원칙이 위반됨을 알 수 있다.
2. ‘SRP - 단일 책임 원칙’이 위배된다.
※ 단일 책임 원칙이란? 객체는 단 하나의 책임만 가져야 한다.
if(animal instanceof Cat cat) {
cat.moveToCatTower();
}
instanceof 함수를 사용함으로써, animal은 Cat에 대한 책임을 가지게 되었다.
하나의 클래스는 하나의 기능 담당하여 하나의 책임을 수행해야 되는데,
animal은 Cat에 대한 책임을 가지게 되며, SRP 원칙을 위반이 된다.
3. ‘캡슐화’ 위배된다.
※ 캡슐환란? 객체가 가진 상태나 행위를 다른 이가 사용하거나 보지 못하도록 숨기는 것을 의미한다.
외부에서 추상된 상위 계층인 animal를 사용하는 입장에서는
animal 하위 계층이 Cat인 경우를 알 필요도 없고, 알아서도 안된다.
instanceof로 인하여 추상화가 깨지게 되며, 캡슐화도 깨지게 되는 것이다.
해당 함수를 지양하는 가장 큰 원인 중 하나이다.
그러면 어떻게 하라고?
그러면 사용해 되는 경우에는 어쩌라는 말이냐?
자바의 추상화를 사용해 보자.
[예시 코드 1]
public abstract class Animal {
public abstract boolean dogCheck();
}
[예시 코드 2]
public class Dog extends Animal {
public void sound(){
System.out.println("멍멍");
}
@Override
public boolean dogCheck() {
return true;
}
}
[예시 코드 3]
public static void main(String[] args) {
Dog dog = new Dog();
action(dog);
}
private static void action(Animal animal) {
if(animal.dogCheck()){
//비즈니스 로직~
}
}
위의 예제와 같이, 자바의 추상메서드를 사용한다면?
Dog 객체가 Animal을 상속받는 것을 캡슐화할 수 있으며, ‘SRP’ 원칙을 지킬 수 있다.
끝으로
java는 객체지향적 프로그램이다.
‘instanceof’ 함수를 사용해야 되는 경우도 있겠지만, 지양해야 되는 이유도 분명히 알아야 될 필요가 있다.
객체지향의 원칙인 ‘SOILD’를 최대한 지키며 코드를 작성하자.
'JAVA' 카테고리의 다른 글
| [Java] 문자열 연결하기 - concat(), StringBuilder (1) | 2025.02.04 |
|---|