언어/JAVA
[JAVA] Interface
hvoon
2022. 9. 8. 11:24
자바언어에서 제공하는 상속 기능은 일반 클래스이든, 추상클래스이든 단일 상속만을 지원함. 하나의 클래스는 하나의 부모클래스를 가질 수 있음(여러개의 클래스를 상속할 수 없음).
- class SubA extends SuperA, SuperB {} -> 에러
다중 상속을 위해 만들어진 interface
-인터페이스는 제약이 다소 있는 클래스
- 추상클래스보다도 더 상속을 위해서 만들어진 클래스. 다중 상속이 가능.
- class 만들듯이 생성하며, class란 키워드 대신 interface 라는 키워드를 써서 생성
1. 인터페이스는 멤버필드(변수)로 public static final 멤버만 가질 수 있음
2. 추상클래스처럼 일반 멤버변수와 일반 멤버 메서드를 가질 수 없음
3. 인터페이스는 멤버메소드로 public abstract 메서드만 가질 수 있음
interface InterA {
int n1 = 10; // public static final int n1 = 10; 이라고 쓴것과 같음
// public static final 라는 키워들이 생략된 상태
// 인터페이스에는 일반 멤버변수를 만들수 없으며, 위와 같이 단순 멤버변수를 만들어도
// static final 로 인식되서 굵은 남색으로 표시됨
// static final 변수는 변수 생성시 반드시 값을 초기화해줘야 함
// InterA(){} // 에러... 인터페이스는 생성자를 갖을수 없음
// 생성자는 일반클래스와 추상클래스만 만들수 있음
// public void print() {} // 에러... 일반 멤버메서드도 선언이 불가함.
// 인터페이스 내부에 선언할 수 있는 요소
public static final int num = 10;
public abstract void test1();
public void test2(); // abstract 가 생략된 상태이며, 자동으로 추상메서드로 인식됨
}
// 인터페이스를 상속(구현)하는 클래스는 상속(구현)할 클래스 앞에 extends 대신 implements를 씀
class SubA implements InterA{
@Override
public void test1() {
System.out.println("SubA 클래스의 test1 메소드 실행");
}
@Override
public void test2() {
System.out.println("SubA 클래스의 test2 메소드 실행");
}
}
public class Interface01 {
public static void main(String[] args) {
// 인터페이스는 객체를 생성할 수 없음.
// 1. 추상메소드를 포함할 수 있기때문에...
// InterA a = new InterA(); // 에러
// 상속을 통한 다형성 구현에만 인터페이스가 활용됨
// 부모 인터페이스의 레퍼런스를 사용하여 자식 클래스의 객체를 참조 가능
InterA a = new SubA();
// 부모 인터페이스의 레퍼런스를 사용하여 자식 클래스의 오버라이딩된 메소드를 호출
a.test1();
a.test2();
// 자식 인스턴스를 전달인수로 보내고, 부모인터페이스의 레퍼런스를 매개변수로하여 사용 가능
test(a);
}
public static void test(InterA a) {}
}
// 인터페이스들의 생성
interface InterSuper1{
public abstract void interSuper1Method();
}
interface InterSuper2{
public abstract void interSuper2Method();
}
// 인터페이스들끼리의 상속(extends):
// 인터페이스를 인터페이스가 상속할 때는 implements를 쓰지않고 extends를 씀.
// 인터페이스끼리는 다중상속(extends)가 가능
interface InterSub extends InterSuper1, InterSuper2{
public abstract void interSubMethod();
// public abstract void interSuper1Method(); 상속받은 추상메서드
// public abstract void interSuper2Method(); 상속받은 추상메서드
}
// 인터페이스끼리의 extends 는 추상메서드들을 온전히 물려받은 것만으로 마무리하고,
// 추상매서드의 override 의무는 면제됨
// 일반 클래스가 인터페이스를 다수개 implements 했다면 그 인터페이스 들이
// 보유한 추상메서들을 모두 구현(override, implements)해야함
class ClassSub1 implements InterSuper1, InterSuper2{
@Override
public void interSuper2Method() {
System.out.println("interSuper2Method 메서드 입니다");
}
@Override
public void interSuper1Method() {
System.out.println("interSuper1Method 메서드 입니다");
}
}
// 인터페이스 간 상속(extends)이 이루어져 있는 인터페이스를 클래스에서 구현(implements)하는 경우
// 부모 인터페이스의 추상메소드를 포함하여 모두 오버라이딩해야함
class ClassSub2 implements InterSub {
@Override
public void interSuper1Method() {
System.out.println("interSuper1Method 메서드 입니다");
}
@Override
public void interSuper2Method() {
System.out.println("interSuper2Method 메서드 입니다");
}
@Override
public void interSubMethod() {
System.out.println("InterSubMethod 메서드 입니다");
}
}
public class Interface02 {
public static void main(String[] args) {
// 자식 레퍼런스 = 자식 인스턴스
ClassSub1 cs1 = new ClassSub1();
ClassSub2 cs2 = new ClassSub2();
// 부모 레퍼런스 = 자식 인스턴스
// 구현(implements)관계가 있는 부모자식간에만 대입이 가능
InterSuper1 is1 = new ClassSub1(); // 가능
InterSuper2 is2 = new ClassSub1(); // 가능
InterSuper1 is3 = new ClassSub2(); // 가능
InterSuper2 is4 = new ClassSub2(); // 가능
// InterSub is5 = new ClassSub1(); // 불가능 - 에러
InterSub is6 = new ClassSub2(); // 가능
// 상속되고 구현된 메서드만 사용이 가능
cs1.interSuper1Method(); // 가능
cs1.interSuper2Method(); // 가능
// cs1.interSubMethod(); // 에러
cs2.interSuper1Method(); // 가능
cs2.interSuper2Method(); // 가능
cs2.interSubMethod(); // 가능
is1.interSuper1Method(); // 가능
//is1.interSuper2Method(); // 불가능
//is1.interSubMethod(); // 불가능
//is2.interSuper1Method(); // 불가능
is2.interSuper2Method(); // 가능
//is2.interSubMethod(); // 불가능
is3.interSuper1Method(); // 가능
//is3.interSuper2Method(); // 불가능
//is3.interSubMethod(); // 불가능
//is4.interSuper1Method(); // 불가능
is4.interSuper2Method(); // 가능
//is4.interSubMethod(); // 불가능
is6.interSuper1Method(); // 가능
is6.interSuper2Method(); // 가능
is6.interSubMethod(); // 가능
}
}
abstract class Unit{
// 모든 캐릭터가 갖는 공통요소
private int hp; // 현재 체력
private int max_hp; // 최대 체력
Unit(int p){
max_hp = p; // 각 캐릭터 마다 다른 전달값으로 최대 체력과 현재 체력을 설정
hp = (int)(p*0.8);
}
public abstract void move( int x, int y);
//{
// System.out.println("x:" + x + ", y:" + y + "로 이동합니다");
//}
}
class GroundUnit extends Unit{
// GroundUnit 만의 특정요소
GroundUnit(int p){
super(p);
}
@Override
public void move(int x, int y) {
System.out.println("x:" + x + ", y:" + y + "로 뛰어갑니다");
}
}
class AirUnit extends Unit{
// AirUnit 만의 특정요소
AirUnit(int p){
super(p);
}
@Override
public void move(int x, int y) {
System.out.println("x:" + x + ", y:" + y + "로 날아갑니다");
}
}
class Tank extends GroundUnit implements Repairable{
Tank(){
super(150);
// max_hp = 150; // 에러
}
public String toString() {
return "Tank";
}
}
class Dropship extends AirUnit implements Repairable{
Dropship(){
super(120);
}
public String toString() {
return "Dropship";
}
}
class Marine extends GroundUnit{
Marine(){ super(40); }
public String toString() { return "Marine"; }
}
class SCV extends GroundUnit implements Repairable{
SCV(){ super(40); }
public String toString() { return "SCV"; }
//public void repaire( Tank t) {}
//public void repaire( Dropship d) {}
// public void repaire( Marine m) {}
public void repaire( Repairable r ) {
if( r instanceof Unit) {
Unit u = (Unit)r;
}
}
}
interface Repairable {
}
public class Interface03 {
public static void main(String[] args) {
Tank t = new Tank();
Dropship d = new Dropship();
Marine m = new Marine();
SCV s1 = new SCV();
s1.repaire(t);
s1.repaire(d);
// s1.repaire(m); // 치료 불가
}
}