abstract
라는 제어자를 붙혀 추상화 메서드, 클래스를 선언 할 수 있다,
abstract class Person{
abstract int walkTo(); //{} 구현부는 작성하지 않는다
}
추상 메서드를 가지는 클래스는 반드시 추상 클래스이다.
ERROR : class Person{ abstract int walkTo()}
추상 클래스는 직접 호출,참조할 수 없고, 상속을 통해서 완성을 해야한다. 또, 추상 클래스에서 선언된 추상 메서드는 이를 상속받은 클래스에서 오버라이딩을 통해 모두 완성되어야 한다.
abstract class Person{
int x;
abstract void moveTo(int x);
}
class PersonWithWalk extends Person{
void moveTo(int x){
System.out.println("Required Time : " + x);
}
}
class PersonWithBike extends Person{
void moveTo(int x){
System.out.println("Required Time : " + x/2);
}
}
class PersonWithSkate extends Person{
void moveTo(int x){
System.out.println("Required Time : " + x/3);
}
}
Person
의 추상화를 통해 moveTo()
라는 메서드를 자손들이 필요하게 가공하여 사용한다.
추상화가 아니더라도 오버라이딩을 통해 자손들이 필요에 맞게 가공할 순 있다.
하지만, 상속을 통해서 결정되는 Person
에서의 불필요한 구현을 피하고, Person
이 참조되는 실수를 방지할 수 있다. 또, Person
을 상속받는 자식들은 반드시 moveTo()
를 구현하도록 강요되기 때문에 어떤 규칙으로서의 역할도 가능하다.
public class playGround {
public static void play() {
Person[] group = {new PersonWithWalk(), new PersonWithBike(), new PersonWithSkate()};
for(int i = 0; i < 3; i++){
group[i].moveTo(100);
}
}
}
//Required Time : 100
//Required Time : 50
//Required Time : 33
인터페이스란 추상메서드의 집합이다. 인스턴스 변수는 존재 할 수 없다.
interface Walkable{
public static final walkpace = 4;
public abstract void walkTo();
void stop(); // == public abstract stop();
}
인터페이스의 메서드는 모두 public abstract
생략이 가능하다.
인터페이스 간의 상속이 가능하며, 다중 상속도 가능하다
다중상속이 가능한 이유는, 부모들의 메서드 충돌 위험이 존재하지 않기 때문이다
인터페이스의 메서드는 구현부가 없음을 보장할 수 있기에 같은 이름의 메서드를 상속받아도 문제 되지 않는다
interface Walkable{};
interface Runable{};
interface RunningMember extends Walkable, Runable{};
추상메서드의 집합인 인터페이스를 사용하려면 이를 사용하여 구현하여야 한다.
interface Walkable{
void moveTo(int d);
};
interface Singable{
void moveTo(int d);
};
class Person implements Walkable, Sing{
public void moveTo(int d){
System.out.println("Move to "+d);
}
}
이때 주의할 점이 있다. Person
클래스에서의 moveTo
는 인터페이스의 오버라이딩이므로 접근제어자의 범위가 더 넓어야 한다. 인터페이스에서는 public abstract
가 생략되었으므로 오버라이딩을 하기 위해선 public
을 꼭 붙혀야 한다.
package playground;
interface Walkable{
void moveTo(int d);
};
interface Jumpable{
void JumpTo(int h);
};
class Person implements Walkable, Jumpable{
public void moveTo(int d){
System.out.println("Move to "+d);
}
public void JumpTo(int h){
System.out.println("Jump to "+h);
}
}
public class playGround {
public static void play() {
Person me = new Person();
me.moveTo(10); //Move to 10
me.JumpTo(20); //Jump to 10
Walkable meWalk = new Person(); //Move to 10
meWalk.moveTo(10);
// meWalk.JumpTo(10); ERROR
Jumpable meJump = new Person(); //Jump to 10
// meJump.moveTo(10); ERROR
meJump.JumpTo(10);
}
}
인터페이스의 존재는 굉장히 유용하다
독립적인 프로그래밍이 가능하다
클래스의 선언과 구현을 분리하여 다른 클래스들 간의 의존을 낮추어 변경이 용이해진다.
package playground;
interface Printer{
void printMessage();
}
/* 직접 연결 된 경우 (A와 연결)
class NewPrinter{
public void printMessage(Printer A){
A.printMessage();
};
}
*/
class NewPrinter{
public void printMessage(Printer i){
i.printMessage();
};
}
class PrinterA implements Printer{
public void printMessage() {
System.out.println("Here is A");
}
}
class PrinterB implements Printer{
public void printMessage() {
System.out.println("Here is B");
}
}
public class playGround {
public static void play() {
NewPrinter printer = new NewPrinter();
printer.printMessage(new PrinterA()); //Here is A
printer.printMessage(new PrinterB()); //Here is B
}
}
// class newPrinter가 인터페이스 타입을 받아 printMessage()메서드를 사용함으로써,
// PrinterA와 PrinerB와의 관계가 느슨해졌다.
// printer.printMessage(new PrinterB()); 와 같은 변경사항에도 인터페이스를 통해 유연하게 작동한다
표준화가 가능하다
프로토콜 처럼 어떤 규칙으로서의 역할이 가능하다.
package playground;
interface Calculator{
int add(int a, int b);
int substract(int a, int b);
int mutiple(int a, int b);
int divide(int a, int b);
}
//ERROR
class CalculatorA implements Calculator{
public int add(int a, int b) {
return a + b;
}
public int substract(int a, int b) {
return a - b;
}
public int mutiple(int a, int b) {
return a * b;
}
}
// ERROR
// divide() 메소드가 존재하지 않아 컴파일 오류가 표기된다
public class playGround {
public static void play() {
}
}
서로 관계없은 클래스들을 맺을 수 있다.
package playground;
interface Repairable {
void repair();
}
class Unit{
String name;
}
class GroundUnit extends Unit implements Repairable {
void walking(){};
public void repair() {};
}
class FlyingUnit extends Unit implements Repairable {
void flying(){};
public void repair(){};
}
public class playGround {
public static void play() {
Repairable flyingUnit = new FlyingUnit();
Repairable groundUnit = new GroundUnit();
Repairable[] repairUnits = {flyingUnit, groundUnit};
//상속관계가 아닌 FlyingUnit과 GroundUnit을 Repairable이라는 관계로 묶을 수 있다.
}
}