(1) : 미완성클래스라고도 불리며 실제 생성되면 안되는 클래스 (
abstract
키워드 사용)
= 실제 인스턴스가 존재하지 않음
(2) : 일반 클래스와 동일하게 선언 가능하다 (필드, 메소드, 생성자) 모두 선언가능
(3) : 자체적으로 객체 생성 ❌ -> 반드시 상속하여 객체 생성해야함
-> 자식클래스를 통해서 추상클래스에 접근 가능함
->Animal animal = new Animal()
추상 클래스로 선언시 생성 불가능 (X)
(4) : abstract 메소드가 포함된 클래스는 반드시 abstract 클래스
abstract 메소드가 없어도 abstract 클래스 선언 가능
abstract class Animal {...}
✅ 추상 메소드
오버라이딩
해야하는 메서드abstract
키워드를 붙어야 한다추상 메서드
가 하나라도 있는 클래스는 추상 클래스
로 선언해야 한다 추상 클래스
안에 추상메소드
, 일반메소드 둘 다 넣을 수 있다추상메소드
는 반드시 자식클래스에서 오버라이딩
해야한다는 점!public abstract void sound();
✅ 순수 추상 클래스
다형성
을 목적으로 사용함오버라이딩
(구현) 해야함public abstract class Animal{
public abstract void sound();
public abstract void move();
}
이러한 순수 추상 클래스
를 더 편리하게 사용하기 위해서 인터페이스
가 등장
- 추상 메소드와, static final 변수를 갖음
- 껍데기 클래스라고 불림
interface
키워드를 사용- 추상클래스와 동일하게 객체 자체 생성 불가능
- 인터페이스 내부에는
추상메소드
만 선언 가능- 순수 추상 클래스에서 약간의 편의기능이 추가된 것이
인터페이스
- 추상메소드에서 사용하던
public abstract
예약어는 생략이 가능public interface Animal{ void sound(); // public abstract void move(); }
- 인터페이스에 변수는 public static final 으로 선언된 상수만 가능하며 public static final 생략 가능
public interface Animal{ int MY_PI = 3.14; // public static final }
- 인터페이스를 구현한 클래스는 인터페이스의 자식 클래스로 설정됨
- 인터페이스는
다중 구현(다중 상속)
을 지원한다
📌 클래스에서 부모 자식 관계는 상속
관계라고 하지만, 인터페이스에서는 구현
관계라고 한다
-> 이유 : 인터페이스는 모두 추상메소드 이기때문에, 기능을 물려받는게 아닌 모두 구현해야함
extends
implements
✅ 인터페이스를 사용해야하는 이유
구현
하라는 제약
을 줌다중 구현(다중 상속)
이 가능✅ 다중 상속은 안되지만 다중 구현은 되는 이유?
다음 그림과 같이 인터페이스 A,B 안에 methodCommon()
메소드가 존재한다
Child
클래스에서 A,B 둘다 구현받았을 때 methodCommon()
메소드를 호출하면
A와 B중 어떤 것이 호출될까?
-> A,B가 아닌 Child에서 오버라이딩 한 methodCommon()
메소드가 호출된다
-> 즉 자식클래스에서 강제로 오버라이딩해야하기 때문에, 부모가 여러명이여도 가능하다!
public class Child implements InterfaceA, InterfaceB {
@Override
public void methodA() {
System.out.println("Child.methodA");
}
@Override
public void methodB() {
System.out.println("Child.methodB");
}
@Override
public void methodCommon() {
System.out.println("Child.methodCommon");
}
}
public class Bird extends AbstractAnimal implements Fly, Swim
상속과 구현 둘 다 나온 경우, extends
가 먼저 나와야함
// CalculatorInterface 인터페이스
package com.inter.common;
@FunctionalInterface // FunctionalInterface로 선언하면 추상메소드는 하나만 저장가능
public interface CalculatorInterface {
void calc(int su, int su2); // 추상메소드이므로 구현 x
// int calc2(int a, int b); -> 추상메소드가 2개이상이면 오류가남
}
// StringInterface 인터페이스
package com.inter.common;
@FunctionalInterface
public interface StringInterface {
String strCheck(String data);
}
// 매개변수 있고, 반환형 없는 람다표현식
CalculatorInterface ci = (int a, int b) -> {
System.out.println(a+b);
};
ci.calc(20, 30);
Flyable f = new Flyable(){ // 익명클래스를 이용해서 구현
@Override
public void fly() {}
};
// 매개변수 없고, 반환형 없는 람다표현식
f = ()->{System.out.println("람다로 날다");};
f.fly();
// 매개변수 있고, 반환형 있는 람다표현식
StringInterface si = (String a) -> {
return a + " 람다로 출력하기";
};
System.out.println(si.strCheck("우와 신기하다"));
// 리턴이 있을 때 로직이 없고 바로 리턴을 구현하면
// return 예약어를 생략할 수 있음 {} 사용하지 않음
si = (String b) -> b + "로직없이 바로 리턴";
System.out.println(si.strCheck("많이 어려워요????"));
}