자바는 객체 지향 프로그래밍(OOP)의 네 가지 주요 원칙인 캡슐화, 상속, 다형성, 추상화를 모두 구현하고 있습니다.
private, protected, public)와 게터/세터를 사용하여 캡슐화를 달성합니다.public class Account { private double balance; public double getBalance() { return balance; } public void deposit(double amount) { this.balance += amount; } }
extends 키워드를 사용하여 이루어집니다. 코드 재사용을 촉진합니다.public class Animal {} public class Dog extends Animal {}
Animal animal = new Dog(); animal.makeSound(); // Dog의 구현을 호출합니다.
public interface Drawable { void draw(); }
자바에서 클래스가 인터페이스와 추상 클래스를 상속받고, 두 클래스 모두 동일한 시그니처를 가진 메소드를 가지고 있다면 어떻게 될까요? 상속된 클래스는 어떤 동작을 보여줄까요?
답변: 추상 클래스와 인터페이스가 동일한 메소드 시그니처를 정의하는 경우, 파생 클래스에서 이 메소드를 한 번만 구현하면 충분합니다. 그러나 추상 클래스가 이 메소드를 구현했다면 자바는 그 구현을 사용합니다. 인터페이스의 디폴트 메소드는 필요할 때만 오버라이드 됩니다.
interface A { default void foo() { System.out.println("A"); }} abstract class B { void foo() { System.out.println("B"); }} class C extends B implements A {} // new C().foo()는 "B"를 출력합니다.
이야기
은행 프로젝트에서는 개발자가 모든 필드를
public으로 설정하고 직접 접근하였습니다. 이로 인해 객체 상태의 통제되지 않는 변경과 오류 추적이 복잡해졌습니다. 결국 모든 코드를 private 필드 및 접근 메소드를 사용하는 것으로 다시 작성해야 했습니다.
이야기
한 신입 직원이 다형성이 지원된다고 생각하며 기본 클래스의 private 메소드를 오버라이드 하려 했습니다. 하지만 사실상 자식 클래스에서 새로운 메소드가 생성되었고, 기본 클래스에서의 호출은 원래 버전을 호출하여 예상치 못한 동작을 일으키게 되었습니다.
이야기
여러 소스에서 디폴트 메소드를 가진 인터페이스를 사용하는 것은 "class X inherits unrelated defaults for Y() from types A and B" 오류를 발생시켰습니다. 직원은 이러한 충돌을 자식 클래스에서 수동으로 해결해야 한다는 사실을 몰랐습니다.