[JAVA] instanceof와 다형성

JHJeong·2024년 4월 1일
0

instanceof 연산자

JAVA의 이항연산자로, 주어진 객체가 특정 클래스나 인터페이스의 인스턴스인지 여부를 확인한다.
이 연산자는 객체 타입을 확인할 때 사용되며, 주로 객체가 특정 타입에 속하는지 확인한 후 해당 타입으로의 안전한 형 변환(downcasting)을 하기 위해 사용됩니다.
아래의 소스 코드는 instanceof 연산자를 사용하는 예제 코드이다. 이 소스 코드에서는 instanceof 연산자를 이용하여 객체 타입을 확인하고, 적절한 타입으로 형변환하여 메소드를 호출하고 있다.

class Animal {
    void makeSound() {
        System.out.println("Some generic sound");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Bark");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Meow");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();

        if (animal instanceof Dog) {
            ((Dog) animal).makeSound();
        } else if (animal instanceof Cat) {
            ((Cat) animal).makeSound();
        } else {
            animal.makeSound();
        }
    }
}

실행 결과
Bark

다형성(Polymorphism)

"많은 형태를 가질수 있는 능력"을 의미하며, JAVA에서는 한 객체가 여러 타입의 인스턴스로 행동할 수 있음을 나타낸다.
다형성을 활용하면 동일한 인터페이스에 대해 서로 다른 구현을 제공할 수 있으며, 이는 코드의 유연성과 재사용성을 높여준다.
다형성은 주로 상속(Inheritance)과 인터페이스(Interface)를 통해 구현된다. 부모 클래스 타입의 참조로 자식 클래스의 인스턴스를 참조할 수 있으며, 이를 통해서 실행 시간에 동적으로 메소드가 결정되는 메소드 오버라이딩(method overriding)이 가능해진다.
다형성을 사용함으로써, 프로그램은 확장성이 높아지며 변경에 유연하게 대응할 수 있습니다. 새로운 클래스가 추가되더라도 기존 코드를 변경하지 않고도 새로운 기능을 통합할 수 있다.
아래의 소스코드는 위의 instanceof연산자를 사용하는 소스코드를 instanceof 연산자 없이 각 객체의 makeSound 메서드를 직접 호출하여 다형성을 이용하는 방식의 소스 코드이다. 이 방식은 Animal 클래스 타입의 참조 변수를 사용하여 Dog 클래스 객체 혹은 Cat 클래스 객체를 참조할 수 있다. 실행시간에 JVM은 객체의 실제 타입에 맞는 makeSound 메소드를 호출한다. 이는 instanceof를 사용하지 않고도 타입에 따라 다른 동작을 수행할 수 있게 해주므로 소스코드가 더 유연해지고 확장성이 더 좋아진다는 장점이 있다.

class Animal {
    void makeSound() {
        System.out.println("Some generic sound");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Bark");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Meow");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();
        // 다형성을 이용하여 해당 객체의 실제 타입에 맞는 메서드를 호출
        animal.makeSound();
        
        animal = new Cat(); // 다형성을 활용해 Cat 인스턴스로 변경
        animal.makeSound(); // Cat의 makeSound 호출
    }
}

실행결과
Bark
Meow

추상화

다형성은 객체에 대한 책임을 분리하는 추상화와 밀접한 관련이 있다. 객체의 실제 구현 내용을 숨기고, 공통된 인터페이스를 통해 서로 다른 객체들을 동일한 방식으로 다룰 수 있게 함으로써, 코드의 의존성을 줄이고 유지보수성을 향상시킨다. 이러한 소스 코드는 객체의 구체적인 타입보다는 인터페이스나 상위 클래스 타입으로 객체를 참조함으로써, 구체적인 구현 변경에도 불구하고 변경 없이 그대로 사용할 수 있게 된다.

instanceof vs 다형성

(1) 유연성과 확장성

instanceof 를 사용하는 코드 : 객체의 타입을 직접 검사하고 타입에 따라 다른 동작을 수행하도록 작성한다. 이 방식은 새로운 타입이 추가될 때마다 해당 타입을 검사하는 소스코드를 매번 추가해야한다. 이렇게 하게 되면 확장성이 낮아진다.
다형성을 사용하는 코드 : 상위 클래스나 인터페이스의 참조를 사용하여 다양한 하위 클래스의 객체를 동일하게 처리할 수 있다. 새로운 클래스를 추가하더라도 상위 클래스나 인터페이스의 메소드를 오버라이드만 하면 되기 때문에, 기존 코드를 변경하지 않고도 새로운 기능을 추가할 수 있다. 이는 시스템의 확장성을 크게 향상시킨다.

(2) 유지보수성

instanceof 를 사용하는 코드 : 소스 코드에 instanceof 검사가 많아질수록, 각 객체 타입을 수동으로 검사하고 적절하게 처리하는 로직이 복잡해진다. 이로 인해 코드의 가독성이 떨어지고 유지보수가 어려워질 수 있다. 특히 새로운 타입이 추가될 때마다 해당 타입을 처리하기 위해서 로직을 계속 추가해야하므로, 코드의 변경사항이 많아지고 오류가 발생할 가능성이 높아진다.
다형성을 사용하는 코드 : 타입 검사나 형 변환 없이도 객체의 실제 타입에 맞는 메소드를 자동으로 호출할 수 있다. 이는 소스코드의 가독성을 향상시키고, 유지 보수를 용이하게 합니다. 새로운 타입이 추가되더라도 상위 클래스의 메서드 호출 방식은 변경되지 않기 때문에, 기존 소스 코드의 수정 없이 새로운 기능을 추가할 수 있다.

요약하게 되면, instanceof 연산자는 타입 확인이 꼭 필요한 경우에 한정적으로 사용되는 반면에, 다형성은 객체 지향 프로그래밍의 핵심 원칙으로, 코드의 재사용성과 확장성을 극대화하는 데 중요한 역할을 한다는 사실을 알 수 있다.

profile
이것저것하고 싶은 개발자

0개의 댓글