본문 바로가기

Java

Java(14) - 인터페이스, 추상 클래스

728x90
반응형

1) 인터페이스

   1-1) 개념

   1-2) 구조

   1-3) 메서드

   1-4) 상속

   1-5) 추상 클래스, 인터페이스 비교

2) 예제 풀이

 

 

 

 

1) 인터페이스

1-1) 개념

  • 클래스를 확장하여 구현
  • 각 클래스의 목적에 맞게 기능을 구현

 

 

1-2) 구조

 

 

1-3) 메서드

 

※ Point

인터페이스의 메서드는 추상 메서드인 형태로 존재해야 하지만, 

JAVA 8 이후로 편의를 위해 구현부가 존재하는 2가지의 메서드를 생성할 수 있다!

 

 

 

1-4) 상속

 

 

 

1-5) 추상 클래스, 인터페이스 비교

 

  • 인터페이스 : implements 라는 키워드처럼 인터페이스에 정의된 메서드를 각 클래스의 목적에 맞게 기능을 구현하는 느낌
  • 추상 클래스 : extends 키워드를 사용해서 자신의 기능들을 하위 클래스로 확장 시키는 느낌

 

 

+) final 키워드

 

 

 

 

2) 예제 풀이

패키지 chapter11.interface_part

Abstract_Sealed.class

package chapter11.interface_part;

abstract sealed class Language permits Java, Cpp, CSharp {}
final class Java extends Language {}
// final class Cpp extends Language {}
// final class CSharp extends Language {}
// final class Python extends Language {}  // 상속 제한

// final class OpenJava extends Java {}  // 상속 제한
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 C30 extends Cpp {} // 상속 제한

final class CSharpCore extends CSharp {} // 상속 제한 안 됨
final class CSharpCore2 extends CSharp {}


public class Abstract_Sealed {

	public static void main(String[] args) {
		/*
		    상속제한
		    final : 더 이상 파생할 수 없다.
		    sealed : 지정한 후손에 대해서만 파생을 허가
		    non-sealed : 제한 없이 파생시킬 수 있다.
		*/
		
		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#");
		}
	}

}

 

 

 

 

TemplateMethod.class

package chapter11.interface_part;

abstract class Car {
	public abstract void drive();
	public abstract void stop();
	
	public void startCar() {
		System.out.println("시동을 켭니다.");
	}
	
	public void turnOff() {
		System.out.println("시동을 끕니다.");
	}
	
	// template 메서드
	final public void run() {
		startCar();
		drive();      // 구현된 생성 클래스 타입의 메서드를 호출
		stop();       // 구현된 생성 클래스 타입의 메서드를 호출
		turnOff();
	}
	
}

class AICar extends Car {
	@Override
	public void drive() {
		System.out.println("자율 주행합니다.");
		System.out.println("자동차가 알아서 방향을 전환합니다.");
	}
	
	@Override
	public void stop() {
		System.out.println("스스로 멈춥니다.");
	}
}

class ManualCar extends Car {
	@Override
	public void drive() {
		System.out.println("사람이 운전합니다.");
		System.out.println("사람이 핸들을 조작합니다.");
	}
	
	@Override
	public void stop() {
		System.out.println("브레이크로 정지합니다.");
	}
}

public class TemplateMethod {

	public static void main(String[] args) {
		System.out.println("==== 자율 주행하는 자동차 ====");
		Car myCar = new AICar();
		myCar.run();
		
		System.out.println("==== 사람이 운전하는 자동차 ====");
		Car hisCar = new ManualCar();
		hisCar.run();
	}

}

 

 

 

 

InterfaceTest.class

package chapter11.interface_part;

interface Calc {     // 원래 인터페이스는 상수, 추상 메서드로만 구성됨!
	// 인터페이스에서 선언한 변수는 "final static"이 생략된 상수
	// 멤버 변수 : 상수
	final static double PI = 3.14;
	int ERROR = -999999999;
	
	
	// 인터페이스에서 선언한 메서드는 "abstract"가 생략된 추상 메서드
	// 멤버 메서드 : 추상 메서드
	abstract int add(int num1, int num2);
	int substract(int num1, int num2);
	int times(int num1, int num2);
	int divide(int num1, int num2);
	
	
	// 하지만 예외로 인터페이스에서 default, static 메서드는 구현부를 가질 수 있다!
	// 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 {
	@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);
	
	@Override
	public abstract int divide(int num1, int num2);
	
}

class CompleteCalc extends Calculator {
	@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) {
		System.out.println(Calc.PI);
		System.out.println(Calc.ERROR);
		int[] arr = new int[] {1, 2, 3, 4, 5};
		System.out.println(Calc.total(arr));
		
		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();
	}

}

 

 

 

 

Multi_Inheritance.class

package chapter11.interface_part;

class HandPhone {
	void call() {
		System.out.println("전화를 건다.");
	}
	
	void receive() {
		System.out.println("전화를 받는다.");
	}
}

interface Camera {
	void takepicture();
}

class HandPhoneCamera extends HandPhone implements Camera {
	@Override
	public void takepicture() {
		System.out.println("찰칵, 사진을 찍는다.");
	}
}

public class Multi_Inheritance {

	public static void main(String[] args) {
		HandPhoneCamera myPhone = new HandPhoneCamera();
		myPhone.call();
		myPhone.receive();
		myPhone.takepicture();

	}

}

interface A {}
interface B {}
interface C extends A, B {}     // 인터페이스들끼리의 다중 상속이 가능함!
// class h extends A, B {}     // 클래스는 다중 상속이 불가능하기에 에러가 발생함!
class D {}
class E extends D implements A, B {}