class MyObject{
private int index;
MyObject(int index) {
this.index = index;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
}
public class ClassType {
public static void main(String[] args) {
MyObject a = new MyObject(2);
MyObject b = new MyObject(4);
System.out.println(a.getIndex()); // "a" result is 2.
a = b;
System.out.println(a.getIndex()); // "a" result is 4.
b.setIndex(6);
System.out.println(a.getIndex()); // "a" result is 6.
}
}
인터페이스의 특성
implements
를 이용해 구현함인터페이스를 사용하는 이유
```java
class ZooKeeper {
void feed(Tiger tiger) { // 호랑이가 오면 사과를 던져 준다.
System.out.println("feed apple");
}
void feed(Lion lion) { // 사자가 오면 바나나를 던져준다.
System.out.println("feed banana");
}
}
```
```java
interface Predator {
Stirng getFood()~~{}~~;
~~int age()~~
}
class Tiger extends Animal implements Predator {
public String getFood() {
return "apple";
}
}
class Lion extends Animal implements Predator {
public String getFood() {
return "banana";
}
}
class ZooKeeper {
void feed(Predator predator) {
System.out.println("feed "+predator.getFood());
}
}
```
1. 구현체는 여러개가 될 수 있지만 인터페이스는 하나임
→ 파라미터로 받는 클래스에 의존적인 클래스 → 파라미터 클래스와는 상관없는 독립적인 클래스가 됨
디폴트 메서드, 스태틱 메서드 - interface에서 미리 메서드 선언 가능
interface Predator {
String getFood();
(public static final) int pie = 3.14;
default void printFood() {
System.out.printf("my food is %s\n", getFood());
}
int LEG_COUNT = 4; // 인터페이스 상수 - 자동으로 public static fianl 설정됨
static int speed() {
return LEG_COUNT * 30;
}
}
abstract class Predator extends Animal { //추상 클래스 선언
abstract String getFood(); //추상 메소드 선언
public static final int LEG_COUNT = 4; // 추상 클래스의 상수는 static 선언이 필요하다. - static은 아래에서 확인
void printFood() {
System.out.printf("my food is %s\n", getFood());
}
int speed() {
return LEG_COUNT * 30;
}
}
class Tiger **extends Predator** implements Barkable {
@Override // 추상메소드여도 @Override 어노테이션을 붙인다.
String getFood(){
(...생략...)
}
}
interface | 추상 클래스 | |
---|---|---|
메소드 | 인터페이스는 구조체이므로 메소드 내용이 없다. | 추상클래스는 일반 클래스처럼 객체 변수, 생성자 등을 가질 수 있다. |
변수 | 선언시 자동으로 public static fianl이 붙어 변경이 불가능하다 | 선언시 접근제한자, 정적 여부, 상수 여부를 직접 선언한다. |
→ 일반 클래스에서의 선언과 동일 | ||
상속 | 다중 상속 가능(implements) | 단일 상속(extends) |
구현 | 모든 메소드 구현 강제(default, static 제외) | 추상 메소드만 구현 강제(@Override 어노테이션 사용), 이미 구현된 메소드는 자율 |
💡 추상클래스: 클래스는 상속받아서 기능을 이용하고 확장 시킴
인터페이스: 함수의 껍데기만 선언하고 함수의 구현을 강제하여 구현 객체의 같은 동작을 보장
참고: 자바의 추상 클래스와 인터페이스 (brunch.co.kr), [초급 JAVA]자바 interface 와 abstract 예제로 이해하기 (tistory.com)
이것을 응용하면 상위 타입에 대해 다양한 하위 타입을 적용하여 다형성을 이용할 수 있음.
부모 클래스 변수 타입에 자식 클래스 변수를 할당하면 자식에서 부모로 자동으로 타입이 변환됨.
자동 타입 변환된 부모 클래스에서 자식 클래스에 의해 오버라이드된 메소드를 호출하면, 오버라이드된 메소드가 호출됨.
class Parent { ... }
class Child extends Parent { ... }
...
Parent pa = new Parent(); // 허용
Child ch = new Child(); // 허용
Parent pc = new Child(); // 허용
Child cp = new Parent(); // 오류 발생.
필드의 타입은 변함이 없지만 실행 도중에 어떤 객체를 필드로 저장하느냐에 따라 실행 결과가 달라질 수 있음
예를 들어, 우리가 Tire라는 부모 클래스를 만들었다고 가정해 보자. 그런데 기술이 점점 발전하거나, 기기가 고장이 나서 타이어를 교체해야 하는 상황이 왔다고 하자. 이때, 만약 부모 타입의 클래스를 상속 받은 자식 객체에서, 더 좋은 기능을 장착한 후(오버라이딩), 타이어를 해당 타이어로 업그레이드할 수 있다면 어떨까?
새로 교체되는 타이어 객체는 기존 타이어와 사용 방법은 동일하지만 실행 결과는 더 우수하게 나와야 함.
→ 상속과 오버라이딩, 타입 변환을 이용하여 프로그램으로 구현