💁♀️ 추상클래스(Abstract Class)란,
추상메소드를 0개 이상 포함하는 클래스로써, 사용하기 위해서는 추상클래스를 상속받은 하위 클래스를 이용해서 인스턴스를 생성 (다형성을 활용)
- 추상클래스로는 인스턴스를 생성할 수 없음
💁 추상메소드(Abstract Method)란,
메소드의 선언부만 있고 구현부가 없는 메소드.
반드시 abstract 키워드를 메소드 헤드에 작성 하여야 함
🙋 잠깐 ! 왜 추상클래스를 사용해야하나요?
- 추상클래스의 추상메소드는 오버라이딩에 대한 강제성이 부여 됨
따라서, 필수 기능을 정의하여 강제성을 부여해 개발 시 일관된 인터페이스를 제공하기 위해 사용
public abstract class Product {
private int nonStaticField;
private static int staticField;
public Product() {}
>>> 상속한 클래스에서 Product pro = new Product(); 처럼 인스턴스 생성 불가
>>> 대신 Product pro = new SmartPhone(); 처럼 다형성을 적용하여 인스턴스 생성은 O
public void nonStaticMethod() {
System.out.println("Product 클래스의 nonStaticMethod 호출함...");
}
public void StaticMethod() {
System.out.println("Product 클래스의 StaticMethod 호출함...");
}
public abstract void abstMethod(); >>> 메소드의 바디({})대신 ;로 메소드 작성 마침
📌 Ref.
* 추상 메소드(미완성 메소드)를 가질 수 있음 (추상 클래스만의 장점)
* 추상 메소드를 1개 이상 가질 경우 반드시 추상 클래스여야 함
* 추상 메소드가 0개인 경우 선택적으로 클래스에 abstract 키워드를 작성하여 인스턴스 생성을 막을 수 있음
* 의도적으로 추상메소드가 없더라도 추상클래스를 만들 수 있다 (인스턴스 생성을 막기 위해)
public class SmartPhone extends Product {
이 때, 추상 클래스가 가지는 추상 메소드를 반드시 오버라이딩 해야함 (강제성 부여)
@Override
public void abstMethod() {
System.out.println("Product 클래스의 abstMethod를 오버라이딩 한 메소드 호출함...");
}
public void printSmartPhone() {
System.out.println("SmartPhone 클래스의 printSmartPhone 메소드 호출함...");
}
}
📌 Ref.
* SmartPhone클래스 내에 Product클래스의 추상메소드인 abstMethod를 오버라이딩 하지않았을 경우,
The type SmartPhone must implement the inherited abstract method Product.abstMethod() 오류
=> 상속한 클래스의 추상메소드를 반드시 오버라이딩 해야함(오버라이딩 강제화)
public class Application {
public static void main(String[] args) {
// Product product = new Product();
>>> Cannot instantiate the type Product 오류
SmartPhone smartPhone = new SmartPhone();
System.out.println(smartPhone instanceof SmartPhone); // true
System.out.println(smartPhone instanceof Product); // true
Product product = new SmartPhone();
>>> 추상 클래스는 미완성이지만 레퍼런스 타입으로 사용하는 것은 아무 문제 없음
product.abstMethod();
>>> Product 추상 클래스와 연결된 것처럼 보임(정적 바인딩)
>>> but, SmartPhone 클래스의 abstMethod를 호출(동적 바인딩)
product.nonStaticMethod();
product.StaticMethod();
}
}
💁♀️ 인터페이스(Interface Implements)란,
추상메소드와 상수 필드만 가질 수 있는 클래스의 변형체
🙋 잠깐 ! 왜 인터페이스를 사용해야하나요?
- 추상클래스와 비슷하게 필요한 기능을 공통화 해서 강제성을 부여할 목적 (표준화)
- 자바의 단일상속의 단점을 극복 (다중 상속)
public interface InterProduct /*extends java.io.Serializable, java.util.Comparator*/ {
📌 Ref.
* 인터페이스가 인터페이스를 상속 받을 시에는 extends 키워드를 사용하며,
여러 인터페이스를 다중 상속 받을 수 있음
public static final int MAX_NUM = 100; >>> 상수 필드는 초기화를 동시에
📌 Ref.
* public static final 제어자 조합을 '상수 필드'라고 부름
반드시 선언과 동시에 초기화 해주어야 함
int MIN_NUM = 10;
// public InterProduct() {}
>>> Interfaces cannot have constructors 오류
// public void nonStaticMethod() {}
>>> Abstract methods do not specify a body 오류
public abstract void nonStaticMethod();
void abstMethod();
📌 Ref.
* 인터페이스 안에 작성한 메소드는 묵시적으로 public abstract의 의미를 가짐
(추상 메소드만 작성 가능하므로)
따라서 인터페이스의 메소드를 오버라이딩하는 경우, 접근 제한자를 public으로 해야 오버라이딩 가능
public static void staticMethod() {
System.out.println("InterProduct 클래스의 staticMethod 호출됨...");
}
public default void defaultMethod() { >>> default : 인터페이스 안에서만 가능
System.out.println("InterProduct 클래스의 defaultMethod 호출됨...");
}
}
// public class Product extends InterProduct {
>>> The type InterProduct cannot be the superclass of Product; a superclass must be a class 오류
public class Product extends java.lang.Object implements InterProduct, java.io.Serializable {
>>> 또한, 인터페이스는 다중 상속 받을 수 있고 extends로 다른 클래스를 상속 받는 경우에도,
>>> 그것과 별개로 인터페이스 추가 상속이 가능
@Override
public void nonStaticMethod() {
System.out.println("InterProduct의 nonStaticMethod 오버라이딩한 메소드 호출됨...");
}
@Override
public void abstMethod() {
System.out.println("InterProduct의 abstMethod 오버라이딩한 메소드 호출됨...");
}
// @Override
public static void staticMethod() {}
>>> The method staticMethod() of type Product must override or implement a supertype method 오류
// public default void defaultMethod() {}
>>> Default methods are allowed only in interfaces 오류
@Override
public void defaultMethod() { >>> default 키워드를 제거하면 오버라이딩 가능
System.out.println("Product 클래스의 defaultMethod 호출됨...");
}
}
public class Application {
public static void main(String[] args) {
// InterProduct interProduct = new InterProduct();
>>> Cannot instantiate the type InterProduct 오류
InterProduct interProduct = new Product();
interProduct.nonStaticMethod();
interProduct.abstMethod();
>>> 정적으로는 InterProduct와 연결된 것처럼 보이나,
>>> 동적으로는 오버라이딩한 Product의 메소드가 호출됨
interProduct.defaultMethod();
>>> Product클래스의 defaultMethod메소드를 주석 처리 후,
>>> 위 식을 호출하면 InterProduct클래스의 defaultMethod메소드가 호출
InterProduct.staticMethod(); >>> 레퍼런스변수명.메소드명();이 아님
System.out.println(InterProduct.MAX_NUM);
System.out.println(InterProduct.MIN_NUM);
}
}