-
Ctrl + Alt + V- 선택한 표현식을 지역 변수로 추출하는 단축키.
-
Ctrl + Alt + M- 선택한 코드 블록을 새로운 메서드로 추출.
- 다양한 형태, 여러 형태를 뜻한다.
- 프로그래밍에서 다형성은 한 객체가 여러 타입의 객체로 취급될 수 있는 능력을 뜻한다.
- 하나의 객체가 다른 타입으로 사용될 수 있다.
- 변수나 값이 어떤 종류의 데이터인지 나타낸다.
- 변수나 값에 대해 어떤 연산이 가능한지 결정한다.
- 컴파일러가 타입을 검사해 프로그램이 안전하게 실행되도록 보장한다.
- 자바에서 변수 선언만으로는 객체가 만들어지지 않는다.
new키워드를 사용해 인스턴스를 생성할 때 메모리가 할당된다.
-
부모 타입의 변수가 자식 인스턴스를 참조하는 것.
- 예시:
Parent poly = new Child(); poly.parentMethod();
- 예시:
-
Child인스턴스를 생성하면 메모리 상에Child와Parent가 모두 생성된다. -
생성된 참조값을 부모 타입 변수(
poly)에 담는다. -
부모 타입은 자식 타입을 담을 수 있다.
- 반대로 자식 타입은 부모 타입을 담을 수 없다.
- 부모 타입 변수로 자식 객체를 담으면 부모의 기능만 안전하게 사용 가능하다. (업캐스팅)
- 자식 타입 변수로 부모 객체를 담으면 자식 고유 기능이 없어서 위험하다. (다운캐스팅 필요, 자동 변환 불가)
-
상속 관계에서는 부모 방향으로 찾아 올라갈 수 있지만 자식 방향으로는 내려갈 수 없다.
-
다형적 참조의 핵심: 부모는 자식을 품을 수 있다.
-
부모 타입 변수를 자식 타입 변수로 대입하려 하면 컴파일 오류가 발생한다.
- 다운캐스팅(캐스팅)을 사용해 부모 타입을 잠깐 자식 타입으로 변경할 수 있다.
- 업캐스팅: 부모 타입으로 변경 (생략 가능, 자주 사용됨)
- 다운캐스팅: 자식 타입으로 변경 (생략 불가, 주의 필요)
public class CastingMain4 {
public static void main(String[] args) {
Parent parent1 = new Child();
Child child1 = (Child) parent1;
child1.childMethod(); // 정상 실행
Parent parent2 = new Parent();
Child child2 = (Child) parent2; // 런타임 오류 - ClassCastException
child2.childMethod(); // 실행 불가
}
}- parent2는 부모 타입으로 객체를 생성했으므로 자식 타입이 존재하지 않는다.
- 이렇게 사용할 수 없는 타입으로 다운캐스팅하면
ClassCastException예외가 발생한다.
- 변수가 참조하는 인스턴스의 타입을 확인할 수 있다.
- 부모에게서 상속받은 메서드를 자식이 재정의하는 것.
- 오버라이딩된 메서드가 항상 우선권을 가진다.
- 주의: 멤버 변수는 오버라이딩되지 않는다.
- 이름 그대로 추상적인 개념만 제공하는 클래스.
- 실체(인스턴스)가 존재하지 않는다.
- 상속을 목적으로 사용되며, 부모 클래스 역할을 담당한다.
abstract class AbstractAnimal { ... }- 부모 클래스를 상속받는 자식 클래스가 반드시 오버라이딩해야 하는 메서드.
- 실체가 존재하지 않고, 메서드 바디가 없다.
public abstract void sound();- 추상 메서드가 하나라도 있는 클래스는 추상 클래스로 선언해야 한다.
-
추상 클래스를 사용해 실수로 인스턴스가 생성되는 문제를 방지한다.
-
추상 메서드를 사용해 자식 클래스가 반드시 오버라이딩하도록 강제할 수 있다.
- 예:
sound()메서드를 반드시 구현하도록 강제.
- 예:
- 모든 메서드가 추상 메서드인 추상 클래스.
- 순수 추상 클래스를 더 편리하게 사용할 수 있는 기능.
- 다중 상속의 효과를 낼 수 있다.
- 모든 메서드가 자동으로 추상 메서드이므로
abstract키워드를 생략해도 된다.
- 추상화
- 캡슐화
- 상속
- 다형성
객체 지향 프로그래밍
: 객체 지향 프로그래밍은 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러개의 독립된 단위, 즉 '객체'들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다다.
-
정의
- 소프트웨어는 확장에는 열려(Open) 있고, 수정에는 닫혀(Closed) 있어야 한다.
- 즉, 새로운 기능 추가는 허용하지만, 기존 코드는 수정하지 않아야 한다.
-
이유
- 프로그램이 커질수록 새로운 기능이 계속 추가된다.
- 기능 추가 때마다 기존 코드를 수정하면:
- 기존 코드에 의존하는 부분에서 버그가 발생할 가능성 ↑
- 유지보수 비용 ↑
- 기존 코드는 그대로 두고 새로운 코드만 추가해 기능을 확장할 수 있도록 하면 유지보수성이 높아진다.
class Animal {
String type;
public Animal(String type) {
this.type = type;
}
public void sound() {
if (type.equals("dog")) {
System.out.println("멍멍!");
} else if (type.equals("cat")) {
System.out.println("야옹!");
}
}
}-
문제점
- 새로운 동물이 추가될 때마다
if문을 수정해야 한다. - 코드 수정 → 기존 코드가 변경됨 → OCP 위반!
- 새로운 동물이 추가될 때마다
interface Animal {
void sound();
}
class Dog implements Animal {
public void sound() {
System.out.println("멍멍!");
}
}
class Cat implements Animal {
public void sound() {
System.out.println("야옹!");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
dog.sound();
cat.sound();
}
}-
장점
- 새로운 동물이 추가될 때 새로운 클래스만 만들면 된다.
- 기존 코드(
Main,Animal)는 수정하지 않아도 된다. - 즉, 확장은 열려있고(Open), 기존 코드는 수정하지 않아도 된다(Closed).
- 기존 코드는 건드리지 않고 새 기능을 확장할 수 있게 만들자.
- 다형성(추상 클래스, 인터페이스)을 적극 활용하자.
- 유지보수성과 안정성, 확장성을 높일 수 있다.