클래스: 멤버 변수 (+ 생성자) + 메소드 => 데이터 타입
추상 클래스(abstract class):
- 추상 메소드를 (하나 이상) 가지고 있는 클래스
- 클래스 선언할 때 abstract 키워드를 반드시 써 줘야 함
- 추상 클래스는 인스턴스를 생성할 수 없다. (new 불가능)
추상 메소드(abstract method):
- 원형(prototype)만 선언돼 있고, 메소드 본체가 정의되지 않은 메소드
- 메소드 본체가 없기 때문에 {}부분이 없다.
- 메소드 원형 끝에 ;으로 끝냄.
- 메소드 이름 앞에 abstract 키워드를 반드시 써 줘야 함
추상 클래스를 사용하는 목적은,
추상 클래스를 상속 받는 자식 클래스에 반드시 구현해야 할 메소드가 있을 경우,
그 메소드를 추상메소드로 만들어서 반드시 override하도록 하는데 목적이 있다.
package com.lec.java.oop04;
public class Abstract01Main {
public static void main(String[] args) {
System.out.println("추상 클래스(abstract class)");
// 추상클래스의 인스턴스 생성은 불가능!
// TestAbstract test1 = new TestAbstract(); // 에러
TestClass test2 = new TestClass();
test2.test = 100;
System.out.println(test2.testMethod()); // 자식클래스에서 '구현' 되었기 때문에 사용 가능.
// 다형성
TestAbstract test3 = new TestClass();
test3.test = 999;
System.out.println(test3.testMethod());
System.out.println("\n 프로그램 종료");
} // end main()
} // end class
abstract class TestAbstract{
int test;
public int getTest() {return test;}
// 추상 메소드
// 수식어 리턴타입 메소드이름(매개변수들, ...);
// 추상 메소드에는 abstract라는 키워드를 반드시 써 줘야 함.
public abstract int testMethod();
}
//추상 클래스를 상속받는 클래스는 반드시 추상메소드를 구현(implement)해야 함 (= 부모쪽의 추상메소드를 오버라이딩하는 것)
//추상 메소드의 본체({ ... })를 만들어줘야 함
class TestClass extends TestAbstract {
@Override
public int testMethod() {
return test;
}
}
인터페이스(interface):
1. 모든 메소드가 public abstract으로 선언되고,
2. 모든 멤버 변수가 public static final로 선언된
특별한 종류의 추상 클래스
- 인터페이스는 interface라고 선언
- 인터페이스를 구현(상속)하는 클래스에서는 implements 키워드를 사용
- 인터페이스를 구현(상속)할 때는 개수 제한이 없다. (다중상속)
- 메소드 선언에서 public abstract는 생략 가능
- 멤버 변수 선언에서 public static final은 생략 가능
[인터페이스 예시 코드1]
public class Interface01Main {
public static void main(String[] args) {
System.out.println("인터페이스(interface)");
TestImpl test1 = new TestImpl();
test1.testAAA();
test1.testBBB();
TestImpl2 test2 = new TestImpl2();
test2.testAAA();
test2.testBBB();
test2.testCCC();
// System.out.println(test2.MIN);
System.out.println(TestInterface.MIN);
System.out.println(TestInterface2.MIN);
System.out.println("\n 프로그램 종료");
} // end main()
} // end class
interface TestInterface {
// 모든 멤버변수는 public static final
public static final int MIN = 0;
int MAX = 100; // public static final 생략.
// 모든 메소드는 public abstract 로 선언
public abstract void testAAA();
void testBBB(); // public abstract 생략.
}
interface TestInterface2{
public static final int MIN = 1;
public abstract void testAAA();
public abstract void testCCC();
}
// 인터페이스는 인스턴스를 구현할 수 없고,
// 다른 클래스에서 구현(implement)해야 함.
class TestImpl implements TestInterface {
@Override
public void testAAA() {
System.out.println("testAAA");
}
@Override
public void testBBB() {
System.out.println("testBBB");
}
}
// 인터페이스는 다중상속이 가능하다.
class TestImpl2 implements TestInterface, TestInterface2 {
// testAAA() 는 양쪽 인터페이스에 다 있었지만
// 한번만 implement 하면 된다.
@Override
public void testAAA() {
System.out.println("testAAA");
}
@Override
public void testBBB() {
System.out.println("testBBB");
}
@Override
public void testCCC() {
System.out.println("testCCC");
}
}
[인터페이스 예시 코드2]
package com.lec.java.oop07;
public class Interface03Main {
public static void main(String[] args) {
System.out.println("인터페이스와 다형성");
TestImple t1 = new TestImple();
t1.testAAA();
t1.testBBB();
System.out.println();
InterfaceAAA t2 = new TestImple();
t2.testAAA();
// t2.testBBB();
// 인스턴스는 TestImple 타입으로 생성됐지만,
// 참조변수의 선언이 InterfaceAAA 타입으로 선언됐기 때문에
// testAAA()만 보이고, testBBB()는 보이지 않는다.
// 형변환(Casting)을 통해서 InterfaceBBB에 선언된 메소드를 사용 가능
((TestImple)t2).testBBB();
System.out.println();
InterfaceBBB t3 = new TestImple();
t3.testBBB();
// t3.testAAA();
((TestImple)t3).testAAA();
System.out.println("\n 프로그램 종료");
} // end main()
} // end class
package com.lec.java.oop07;
// 인터페이스를 구현(implements)하는 클래스에서
// 인퍼페이스에 선언만 돼있는 메소드들을 구현(정의)해야 함
public class TestImple implements InterfaceAAA, InterfaceBBB{
@Override
public void testBBB() {
System.out.println("InterfaceBBB : test 구현");
}
@Override
public void testAAA() {
System.out.println("InterfaceAAA : test 구현");
}
} // end class TestImple
package com.lec.java.oop07;
// 인터페이스에 선언되는 모든 메소드는 public abstract임
// public abstract는 생략 가능
// 인터페이스에 선언되는 메소드는 본체({ ... })가 없음
// 메소드 선언 끝에는 세미콜론(;)으로 끝냄
public interface InterfaceAAA {
public abstract void testAAA();
} // end interface InterfaceAAA
package com.lec.java.oop07;
public interface InterfaceBBB {
public abstract void testBBB();
} // end interface InterfaceBBB