지침 가이드 역할을 하는 기준 클래스
불완전한 클래스
완전하지 않기 때문에 new
할 수 없다! (객체 생성x)
(이 클래스를 상속받는 자식을 정의하여 자식을 new
해야함)
추상 메서드를 하나라도 포함하고 있으면 반드시 추상 클래스로 선언
물론 일반 메서드 넣을 수 있음
형식: abstract
| class | 클래스명{abstract
| 반환형 | 메서드명( ) ; }
불완전한 메서드(=추상 메서드) 만드는 방법 : abstract
수식자 + { }
없애기
abstract
수식자는 "추상적인"이란 뜻이며
메서드나 클래스에 적용가능
변수에는 붙일 수 없음 (구현하지 않을 몸체가 없기 때문...)
'수식자'와의 첫 만남
추상 클래스를 상속받는 자식 클래스도 추상 클래스도 정의될 수 있음
(“추상 클래스의 자식이 다시 추상 클래스가 되는 것”
== “구현 책임을 미루는 것”)
자식 메서드는 추상 메서드를 완전하게 구현할 의무를 가짐
➡ 일종의 안전장치!⛑
안하면 컴파일 에러남
abstract class Animal {
abstract void sound(); // 구현 강제!
}
class Dog extends Animal {
// 부모의 메서드를 자식이 재정의하는 메서드 정의기법
// '오버라이딩' 의무가 생김
void sound() {
System.out.println("멍멍");
}
}
Java는 다중상속을 금지을 금지하지만, 현실은 '다중 상속'처럼 작동
이에 대한 Java의 해결 방법: ✅ 인터페이스
인터페이스: 메서드의 시그니처만 정의하고, 구현은 자식 클래스에게 위임
(객체아니므로 다중상속 금지 조건에 해당 X
객체에서 “기능만 쏙 뺀 것”)
interface Animal {
int LEGS = 4; // public static final 자동 적용
void sound(); // public abstract 자동 적용
}
implements
B// 인터페이스 선언
public interface Flyable {
public void fly(); // 나는 기능
}
// class에서 인터페이스 구현
class Bird implements Flyable {
public void fly() {
System.out.println("새가 하늘을 납니다");
}
}
// 사용하기
public class Test {
public static void main(String[] args) {
Flyable f = new Bird(); // 인터페이스 타입으로 다형성 활용
f.fly(); // 출력: 새가 하늘을 납니다
}
}
항목 | 추상 클래스 | 인터페이스 |
---|---|---|
키워드 | abstract class | interface |
다중 상속 | ❌ 안 됨 | ✅ 다중 구현 가능 |
메서드 | 일반 메서드 O, 추상 메서드 O | Java 7까지: 추상 메서드만 Java 8 이후: default, static O Java 9 이후: private도 가능 |
변수 | 일반 필드 O | public static final 상수만 가능 |
생성자 | O (호출 가능) | ❌ 없음 |
사용 목적 | 상속 관계에서 공통 기능 제공 | 기능 규약 정의, 역할 위임 |
상속 방법 | extends (단일 상속) | implements (다중 구현) |
예시 | abstract class Animal | interface Flyable |
상수 (항상 상'常'數, constant): 변하지 않는 수
(1) 상수는 모든 인스턴스가 제한 없이 접근할 수 있어야 한다.
(2) 상수는 모든 인스턴스 간 공유될 수 있어야 한다.
(모든 인스턴스가 공통으로 이 값을 공유)
(3) 상수는 프로그램이 실행되는 동안 그 값이 변해서는 안된다
이 조건들을 충족하게 각 자리를 채워 넣으면
➡ (public
)(static
)(final
) int x = 3;
ex) BorderLayout 클래스 내부에 있는 상수 변수
public static final String NORTH = "North";
"North" 라는 문자열 값에 모두 제한 없이 접근할 수 있게(
public
) 하고 클래스명으로 직접 접근 가능하게(static
) 만들고
절대 바뀌지 않게(final
) 만들었음.
안그래도 어제 super( )공부하면서 찾아봤지
Java 생성자에서는 this()
또는 super()
중 하나만 호출할 수 있고, 둘 다 생략하면 super()
가 자동으로 붙음
(자동 생성되는 super();는 매개변수가 없는 기본 생성자)
class X {
X() { System.out.print(1); }
X(int x) {
this(); System.out.print(2);
}
}
public class Y extends X {
Y() { super(6); System.out.print(3); }
Y(int y) {
this(); System.out.println(4);
}
public static void main(String[] a) { new Y(5); } // 1234 출력
}
new Y(5) → Y(int y)
↓
this(); // → Y() 호출
↓
Y() {
super(6); // → X(int) 호출
↓
this(); // → X() 호출
→ print(1)
→ print(2)
→ print(3)
}
→ print(4)
자료형은 서랍장 개념
메서드는 this
바인딩으로 찾기!
class Foo {
public int a = 3;
public void addFive() {
a += 5;
System.out.print("f ");
}
}
class Bar extends Foo {
public int a = 8; // 필드 "숨김" (hiding)
public void addFive() {
this.a += 5;
System.out.print("b ");
}
}
Foo f = new Bar();
f.addFive(); // 동적 바인딩
System.out.println(f.a); // 정적 바인딩
//출력: b 3
addFive()
는 오버라이딩 되었기 때문에 →Bar의 addFive()
실행됨 → b 출력그런데
f.a
는 Foo 타입 기준으로 보므로 →Foo.a
즉, 3 출력됨this.a += 5;는 Bar의 a, 즉 8 + 5 = 13 되었지만,
f.a는 Foo의 a라서 여전히 3
종류 | 바인딩 시점 | 기준 |
---|---|---|
정적 바인딩 (static binding) | 컴파일 시점 | 자료형 기준 (서랍장) |
동적 바인딩 (dynamic binding) | 실행 시점 | 실제 인스턴스(this) 기준 |
필드 숨김(field hiding)은 정적 바인딩에서 일어남.
즉, 변수(필드)는 참조 변수의 자료형(타입)을 기준으로 컴파일 시점에 결정되기 때문에 발생하는 현상 (메서드 오버라이딩처럼 런타임에 바뀌는 구조가 아님)