-
[자바의 정석] 추상클래스 인터페이스 내부클래스 정리JAVA 2022. 10. 19. 09:58728x90반응형
추상 클래스(Abstract class)
클래스를 설계도라고 하면 추상 클래스는 미완성된 설계도를 말하며 다른 클래스의 작성을 돕기 위하 목적으로 사용됩니다.
- 추상 클래스는 추상 메서드를 포함하고 있는 클래스를 말합니다.
- 일반 메서드는 추상 메서드를 호출할 수 있습니다.
- 추상 클래스는 인스턴스를 생성할 수 없습니다.
abstract class Player{ // 추상 클래스 int currentPos; Player(){ currentPos = 0; } abstract void play(int pos); // 추상 메서드 abstract void stop(); // 추상 메서드 void play(){ // 오버로딩 play(currentPos); // 추상 메서드 호출 } }
추상 메서드(Abstract Method)
선언부만 있으며 구현부가 없는 메서드를 말하며 꼭 필요하지만 자식 클래스마다 다르게 구현될 것으로 예상되는 경우에 사용됩니다.
- 추상 클래스를 상속받은 자식 클래스는 추상 메서드를 모두 구현해야 사용 가능합니다.
- 추상 메서드를 구현한다는 것은 오버 라이딩을 하는 것이기 때문에 오버 라이딩 규칙을 따라야 한다.
abstract class Player{ abstract void play(int pos); // 추상 메서드 abstract void stop(); // 추상 메서드 } class AudioPlayer extends Player{ void play(int pos){/*내용생략*/} void stop(){/*내용생략*/} } abstract class AbstractPlayer extends Player{ void play(int pos){/*내용생략*/} // 추상 메서드 stop을 구현하지 않았기 때문에 추상 클래스가된다. }
추상 클래스의 작성
여러 개의 클래스에 공통적으로 사용될 수 있는 부분을 뽑아서 추상 클래스로 작성하게 됩니다.
// 클래스 예제 class Marine{ int x,y; // 공통 되는 부분 void move(int x, int y){} // 공통 되는 부분 void stop(){} // 공통 되는 부분 void stimPack(){} } class Tank{ int x,y; // 공통 되는 부분 void move(int x, int y){} // 공통 되는 부분 void stop(){} // 공통 되는 부분 void changeMode(){} } class Dropship{ int x,y; // 공통 되는 부분 void move(int x, int y){} // 공통 되는 부분 void stop(){} // 공통 되는 부분 void load(){} void unload(){} } // 공통 되는 부분을 추상 클래스로 만든다. abstract class Unit{ int x, int y abstract void move(int x, int y); void stop(){} } class Marine extends Unit{ void move(int x, int y){} void stimPack(){} } class Tank extends Unit{ void move(int x, int y){} void changeMode(){} } class Dropship extends Unit{ void move(int x, int y){} void load(){} void unload(){} } // 다형성을 이용해서 부모 타입의 참조변수로 자식 타입의 객체를 다룬다. Unit[] group = new Unit[4]; group[0] = new Marine(); group[1] = new Tank(); group[2] = new Marine(); group[3] = new Dropship(); for(int i = 0; i < 4; i++){ group[i].move(100,200); // 메서드가 중복되는 경우 실제 생성된 인스턴스에 있는 메서드를 호출하게 된다. // 그러므로 move는 추상 메서드를 호출하는게 아니다. }
인터페이스(interface)
인터페이스는 일종의 추상 클래스이며 실제로 구현된 것이 전혀 없는 기본 설계도이다.
- 인터페이스에서는 추상 메서드, 디폴트 메서드, static 메서드, 상수만을 가질 수 있다.
- 인스턴스를 생성할 수 없으며 클래스 작성에 도움을 줄 목적으로 사용된다.
- 개발 시간을 단축할 수 있으며 표준화가 가능하다.
- 서로 관계없는 클래스들에게 관계를 맺어줄 수 있다.
인터페이스의 작성
인터페이스의 멤버 중 추상 메서드와 상수의 경우 제어자를 생략할 수 있습니다.
인터페이스의 모든 멤버 변수는 public static final이기 때문에 생략 가능하다.
인터페이스의 모든 메서드는 public abstract이기 때문에 생략 가능하다.// 기본 작성 방법 interface InterfaceName{ public static final int NUMBER = 1; public abstract method(/* 매개변수 */); } // 예제 interface PlayingCard{ int SPADE = 4; // public static final 생략 final int DIAMOND = 3; //public static 생략 static int HEART = 2; // public final 생략 int CLOVER = 1; // public static final 생략 public abstract String getCardNumber(); // 추상 메서드 String getCardKind(); // public abstract 생략 }
인터페이스의 상속
인터페이스도 클래스처럼 상속이 가능하며 다중 상속이 허용된다.
- 인터페이스는 Object 클래스와 같은 최고 조상이 없다.
interface Movable{ void move(int x, int y); } interface Attackable{ void attack(Unit u); } interface Fightable extends Movable, Attackable{ } // 인터페이스 다중 상속
인터페이스의 구현
인터페이스를 구현한다는 것은 클래스를 상속받는 것과 같으며 상속 후 모든 추상 메서드를 구현하지 않으면 추상 클래스가 된다.
- 인터페이스는 상속과 구현이 동시에 가능하다.
// 기본 작성 방법 class ClassName implements InterfaceName{ // 인터페이스에 정의된 추상메서드를 구현해야한다. } // 예제 interface Fightable{ // 추상 클래스 void move(int x, int y); // 추상 메서드 void attack(Unit u); // 추상 메서드 } class Fighter implements Fightable{ public void move(int x, int y){} // 만약 void move(){}를 하면 오버라이딩 규칙에 어긋나기 때문에 에러가 발생한다. public void attack(Unit u){} } abstract class Fighter2 implements Fightable{ public void move(int x, int y){} // 추상 메서드 attack을 구현하지 않았기 때문에 추상클래스가 된다. } // 클래스 상속과 인터페이스 구현을 동시에 진행 class Fighter3 extends Unit implements Fightable{ public void move(int x, int y){} public void attack(Unit u){} }
인터페이스를 이용한 다형성
인터페이스 타입의 변수로 인터페이스를 구현한 클래스의 인스턴스를 참조할 수 있다.
- 매개변수로 인터페이스를 지정할 수 있다.
- 메서드의 리턴 타입으로 인터페이스를 지정할 수 있다.
// 인터페이스 타입의 참조변수로 인터페이스를 구현한 클래스의 인스턴스를 생성할 수 있다. class Fighter extends Unit implements Fightable{ public void move(int x, int y){} // 인터페이스를 메서드의 매개변수 타입으로 지정할 수 있다. public void attack(Fightable f){} Fightable method(){ // .... return new Fighter(); } } Fighter f1 = new Fighter(); Fightable f2 = new Fighter();
디폴트 메서드
인터페이스에서 디폴트 메서드와 static 메서드는 JDK 1.8 때 추가되었으며 디폴트 메서드는 인터페이스에 추가된 일반 메서드를 말합니다.
interface MyInterface{ void method(); // 추상 메서드 default void newMethod(){} // 디폴트 메서드 (일반 메서드) }
디폴트 메서드와 기존의 메서드가 충돌하는 경우는 아래와 같이 해결할 수 있다.
경우 해결법 여러 인터페이스의 디폴트 메서드 간의 충돌 클래스에서 디폴트 메서드를 오버라이딩해야한다. 디폴트 메서드와 부모 클래스의 메서드 간의 충돌 디폴트 메서드는 무시된다. interface MyInterface{ default method(){System.out.println("MyInterface method");} } class Parent{ public method(){System.out.println("Parent class method");} } class Child extends Parent implements MyInterface{ } Child c = new Child(); c.method(); // Parent class method (디폴트 메서드 무시된다.)
인터페이스 예제 - 관계 맺어주기
interface Repairable{} // 인터페이스 class Unit{ int hitPoint; final int MAX_HP; Unit(int hp){ // 생성자 MAX_HP = hp; // 생성자로 상수 초기화 } } class GroundUnit extends Unit{ GroundUnit(int hp){ super(hp); // Unit(int hp) 생성자 호출 } } class Tank extends GroundUnit implements Repairable{ Tank(){ super(150); // GroundUnit(int hp) 생성자 호출 hitPoint = MAX_HP; } public String toString(){return "Tank";} } class Marine extends GroundUnit{ Marine(){ super(40); // GroundUnit(int hp) 생성자 호출 hitPoint = MAX_HP; } public String toString(){return "Marine";} } class SCV extends GroundUnit implements Repairable{ SCV(){ super(60); hitPoint = MAX_HP; } void repair(Repairable r){ if(r instanceof Unit){ Unit u = (Unit)r; while(u.hitPoint != u.MAX_HP){ u.hitPoint++; } } } } Tank tank = new Tank(); Marine marine = new Marine(); SCV scv = new SCV(); scv.repair(tank); scv.repair(marine); // Error! Marine클래스는 Repairable인터페이스를 구현하지 않았기 때문이다.
728x90반응형'JAVA' 카테고리의 다른 글
[자바의 정석] Object, String, StringBuffer 클래스 정리 (2) 2022.10.21 [자바의 정석] 예외처리 (0) 2022.10.19 [자바의 정석] 제어자 & 다형성 (0) 2022.10.18 [자바의 정석] 상속 & 오버라이딩 & package & import (0) 2022.10.17 [자바의 정석] 생성자 & 변수의 초기화 (0) 2022.10.14