<aside> 💡 클래스 extends 클래스
클래스 implements 인터페이스
인터페이스 extends 인터페이스
상속제한
final : 더 이상 파생할 수 없음
sealed ~ permits : 지정한 후손에 대해서만 파생을 허가한다.
non-sealed : 제한 없이 파생시킬 수 있다.
<abstract 추상 클래스>
추상클래스
1.추상클래스를 가지고 있는 클래스는 abstract 예약어를 사용(메서드)
2.추상클래스는 객체를 생성 할 수 없다(미완성 클래스 이므로)
3.상속을 통해서만 사용한다(추상클래스는 상속을 위해 만들어진 클래스)
4.추상메서드가 있는 추상클래스를 상속받는 하위 클래스는
"반드시" 추상메서드를 override 해야한다
<인터페이스>
인터페이스에서는 변수를 선언하면 항상 final static 생략되어 있음
인터페이스에서 선언한 메서드는 기본적으로 추상메서드로 변환
- default 사용하면 기본 메서드 만들 수 있음
(호출은 하위클래스에서 추상클래스 구현후 호출가능)
- static 메서드 만들 수 있음
(static 메서드는 호출 가능)
implements 인터페이스를 구현할떄 쓰는 예약어
EX)
class HandPhoneCamera extends HandPhone implements Camera
//클래스HandPhone 를 상속받는 클래스HandPhoneCamera가
//인터페이스 Camera의 takepicture() 구현
//구현 implements //상속 extends
interface A {}
interface B {}
interface C extends A, B {} //인터페이스끼리는 다중상속 가능
// class G extends A, B {} //err
class D {}
class E extends D implements A, B {} //다중구현 가능
template 메서드
//흐름대로 진행
final public void run() { //흐름대로 진행하는 메서드.
statCar();
drive(); //추상메서드
stop(); //추상메서드
turnOff();
}
</aside>
abstract sealed class Language permits Java, Cpp, CSharp {}
//Java, Cpp, CSarp 의 클래스에서만 Language {} 상속 허가 - 1번
final class Java extends Language {} //-2번
//final class Cpp extends Language {}
//final class CSarp extends Language {}
//final class python extends Language {} //err : 1번으로 인해 상속 불가
//final class OpenJva extends Jva {} //err : 2번으로 인해 상속 불가
sealed class Cpp extends Language permits C11, C20 {}
//sealed permits 상속제한 //C11, C20 의 클래스에서만 Cpp{} 상속 허가
non-sealed class CSharp extends Language {} //CSharp는 제한없이 파생시킬 수 있다
//Cpp로부터는 두개의 클래스 파생 가능
final class C11 extends Cpp {}
final class C20 extends Cpp {}
//CSharp 으로부터는 임의의 클래스 파생 가능
final class CSharpCore extends CSharp {}
package chapter11.interface_part1;
abstract sealed class Language permits Java, Cpp, CSharp {} //abstract 추상 클래스 //sealed permits 상속제한
final class Java extends Language {}
sealed class Cpp extends Language permits C11, C20 {}
non-sealed class CSharp extends Language {}
final class C11 extends Cpp {}
final class C20 extends Cpp {}
final class CSharpCore extends CSharp {}
public class Abstract_sealed {
public static void main(String[] args) {
Language lang_java = new Java();
outLanguageName(lang_java);
}
//다형성을 이용해 오버로딩 없이도 활용가능
public static void outLanguageName(Language lang) {
if (lang instanceof Java) {
System.out.println("자바");
}else if (lang instanceof Cpp) {
System.out.println("C++");
}else if (lang instanceof CSharp) {
System.out.println("C#");
}
}
}
<출력결과>
자바
<풀이>
Language lang_java = new Java();
outLanguageName(lang_java); 에서 outLanguageName 메서드가 Language 타입의 매개변수를 받음
(=현재 구현된 내용에서는 Java 클래스의 인스턴스만을 인식)
즉, 메서드 구조를 보면, Java 클래스의 인스턴스인지를 체크함
package chapter11.interface_part1;
abstract class Animal {
//맴버 변수
String name;
//생성자
Animal(String name) {
this.name = name;
}
//맴버 메서드
void alive() {
System.out.println("생물");
}
//추상 메서드
abstract void move();
}
abstract class Human extends Animal{
Human (String name){
super(name);
}
@Override
void move() {
System.out.println("두 발로 걷다");
}
abstract void play(); //abstract 없으면 오류남
}
class Student extends Human {
Student(String name){
super(name);
}
@Override
void play() {
System.out.println("놀다");
}
}
class Tiger extends Animal{
Tiger (String name){
super(name);
}
@Override
void move() {
System.out.println("네 발로 걷다");
}
}
class Eagle extends Animal{
Eagle (String name){
super(name);
}
@Override
void move() {
System.out.println("날다");
}
}
public class AbstractTest {
public static void main(String[] args) {
//Animal a = new Animal(); arr발생 추상클래스는 인스턴스 생성 불가
//Animal b = new Human("사람");
Animal b = new Student("학생"); //상속받아서 더 큰 의미를 나타낼 수 있음
Animal c = new Tiger("호랑이");
Animal d = new Eagle("독수리");
b.alive();
b.move();
c.move();
d.move();
}
}
<출력결과>
생물 두 발로 걷다 네 발로 걷다 날다
package chapter11.interface_part1;
interface Calc {
//final이 생략된 상수 //질문 인터페이스에서는 변수를 선언하면 항상 final static 생략되어 있음
double PI = 3.14; //final static 생략되어 있음
int ERROR = -9999999;
//인터페이스에서 선언한 메서드는 추상메서드로 변환
int add(int num1, int num2); //반환값이 int인 구현체가 존재하지않는 추상메서드 //abstract 생략되어 있음
int substract(int num1, int num2);
int times(int num1, int num2);
int divide(int num1, int num2);
//default 메서드 //인터페이스에서는 기본적으로 추상메서드가 만들어지지만, default 사용하면 기본 메서드 만들 수 있음
default void description() {
System.out.println("정수 계산기를 구현합니다.");
}
//static 메서드
static int total(int[] arr) {
int total = 0;
for (int i : arr) {
total += i;
}
return total;
}
}
abstract class Calculator implements Calc { //interface인 Calc의 추상클래스 add, substract를 클래스 Calculator가 구현
@Override
public int add(int num1, int num2) {
return num1 + num2;
}
@Override
public int substract(int num1, int num2) {
return num1 - num2;
}
// @Override
// public abstract int times(int num1, int num2); //구현 x -> 생략
// @Override
// public abstract int divide(int num1, int num2); //구현 x -> 생략
}
class CompleteCalc extends Calculator { //클래스 Calculator를 상속받은 클래스CompleteCalc에서 Calculator의 추상클래스 times, divide 를 구현
@Override
public int times(int num1, int num2) {
return num1 * num2;
}
@Override
public int divide(int num1, int num2) {
if (num2 != 0) return num1 / num2;
else return Calc.ERROR;
}
public void showInfo() {
System.out.println("Calc 인터페이스를 구현하였습니다.");
}
}
public class InterfaceTest {
public static void main(String[] args) {
int arr[] = {1,2,3,4,5};
System.out.println(Calc.PI); //interface에 직접 접근
System.out.println(Calc.ERROR);
System.out.println(Calc.total(arr));//static 메서드
//default 메서드 호출 불가/ static 영역에 없음 /인스턴스를 통해서만 호출가능 즉 하위클.래.스에서 추상클래스를 구현후 호출가능
CompleteCalc calc = new CompleteCalc();
int num1 = 10, num2 = 5;
System.out.println(calc.add(num1,num2));
System.out.println(calc.substract(num1,num2));
System.out.println(calc.times(num1,num2));
System.out.println(calc.divide(num1,num2));
calc.showInfo();
calc.description();
}
}
<출력결과>
3.14 -9999999 15 15 5 50 2 Calc 인터페이스를 구현하였습니다. 정수 계산기를 구현합니다.