5장_상속과 다형성_기말

IkSun·2023년 4월 27일

5.7 추상 클래스
5.8 인터페이스

5.7 ) 추상 클래스

추상 메소드와 추상 클래스

  • 추상 메소드
    • 선언되어 있으나 구현되어 있지 않은 메소드, abstract 키워드
    • 추상 메소드 선언
      • abstract 키워드로 선언
      • ex) public abstract int getValue();
    • 추상 메소드는 서브 클레스에서 오버라이딩하여 구현해야 함.
  • 추상 클래스의 2종류
    • 추상 메소드를 하나라도 가진 클래스
      • 클래스 앞에 반드시 abstract 라고 선언해야함.
    • 추상 메소드가 하나도 없지만 클래스 앞에 abstract 로 선언된 클래스
//1. 추상 메소드를 포함하는 추상 클래스
abstract class Shape { //추상 클래스 선언
   public Shape() {};
   public void paint() { draw(); }
   abstract public void draw(); //추상 메소드 선언
}

//2. 추상 메소드 없는 추상 클래스
abstract class Person {
   String name;
   public void load(String name){
      this.name = name;
   } 
}

추상 클래스는 객체(인스턴스)를 생성 불가

  • 해당 클래스 또는 메소드의 정의가 정확하게 정의 되어 있지 않기 떄문.
    abstract class Shape {  // 추상 클래스 선언
        public Shape() {};  // 함수가 어떤 역할을 할지 구현 x
        ...
     }
    
     public class AbstractError {
        public static void main(String[] args) }
           Shape shape;  // 참조 변수 생성은 가능 -> 다른 객체의 참조를 저장할 순 있다.
           shape = new Shape();  //컴파일 오류. 추상 클래스는 shape 의 객체를 생성할 수 없다
        }
     }

추상 클래스의 상속

  • 추상 클래스의 상속 2가지 경우

    • 1) 추상 클래스의 단순 상속
      • 추상 클래스를 상속받아, 추상 메소드를 구현하지 않으면 추상 클래스 됨
      • 서브 클래스도 abstract 로 선언해야 함 -> 자식에서도 일반 클래스 처럼 메모리 생성 불가.
        abstract class Shape { // 추상 클래스
            public Shape() {}
            public void paint() {draw();}
            abstract public void draw(); //추상 메소드
         }
         abstract class Line extends Shape { //추상 클래스 draw() 를 상속받기 떄문
            public String toString() {return "Line";}
            //상속 받은 abstract draw() 에 대한 정의가 없다! -> draw() 가 어떻게 수행될지 정보가 없음
         }
    • 2) 추상 클래스 구현 상속
      • 서브 클래스에서 슈퍼 클래스의 추상 메소드 구현(오버라이딩)
      • 서브 클래스는 추상 클래스 아님.

추상 클래스의 용도

  • 설계와 구현 분리
    • 슈퍼 클래스에서는 개념 정의 (껍데기 설계만)
      • 서브 클래스마다 다른 구현이 필요한 메소드는 추상 메소드로 선언
    • 각 서브 클래스에서 구체적인 행위 구현
      • 서브 클래스마다 목적에 맞게 추상 메소드 다르게 구현
      • 동적 바인딩 -> draw() 를 실행하면 실제로 자식에서 역할 수행

예제 5-7 : 추상 클래스의 구현

abstract class Calculator {  //추상 클래스 선언
	public abstract int add (int a, int b);  
	public abstract int subtract (int a, int b);
	public abstract double average (int [] a);
}

public class GoodCalc extends Calculator {
	@Override
	public int add(int a, int b) { // add() 추상 메소드 구현
		return a+b;
	}
    
	@Override
	public int subtract(int a, int b) { // subtract() 추상 메소드 구현
		return a-b;
	}
    
	@Override
	public double average(int [] a) { // average() 추상 메소드 구현
		double sum = 0;
		for (int i=0; i<a.length; i++)
			sum += a[i];
		return sum/a.length;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
        Calculator c = new GoodCalc();  //업캐스팅 -> 부모 영역만 접근 가능 
        								//-> 오버라이딩에 의해서 add 함수 호출 
                                        //-> (동적 바인딩) 자식 클래스 메소드 호출
		//GoodCalc c = new GoodCalc(); 
		System.out.println(c.add(2,3));
		System.out.println(c.subtract(2,3));
		System.out.println(c.average(new int [] {2,3,4}));
	}
}
//result
// 5
// -1
// 3.0

5.8 ) 인터페이스

자바의 인터페이스

  • 인터페이스
    • 구현해야할 메소드들이 선언되는 추상형 타입 -> 정의가 되어 있지 않다
  • 인터페이스 선언
    • public interface SerialDriver { ... }
  • 인터페이스 구성 요소
    • 추상 메소드 :public abstract 셍략 가능
    • 상수 필드 : public 만 허용, public static final 생략 가능
    • default 메소드
      • 인터페이스에서도 어떤 메소드를 정의하는 경우가 희박하지만 그래도 정의할 수 있는 방법중 드물에 default 키워드 등장 (정의 제공)즉 정의가 수행될 수 있는 interface 로 이해하면 된다.
    • private 메소드 :
      • 인터페이스 내에 메소드 코드가 작성되어야 함
      • 인터페이스 내에 있는 다른 메소드에 의해서만 호출 가능
    • static 메소드
      • public, private 모두 지정 가능, 생략하면 public
  • 인터페이스의 특징
    • 인터페이스의 객체 생성 불가 :new PhoneInterface(); -> 오류
    • 단, 인터페이스 타입의 레퍼런스 변수 선언 가능 : PhoneInterface galaxy; -> 참조변수
    • 인터페이스 구현 : 인터페이스를 상속받는 클래스는 인터페이스의 모든 추상 메소드를 반드시 구현해야한다.
      • implements 키워드 사용
      • 여러 개의 인터페이스 동시 구현 가능
    • 다른 인터페이스 상속 가능 -> implement
      • 일반 interface 는 구현을 의미하지만 interface 끼리도 상속이 가능
    • 인터페이스의 다중 상속 가능 -> extends
      • 인터페이스는 부모가 여러개여도 된다!!!(쉼표로 구분)
      • 클래스가 아님 (일반 클래스의 상속은 부모가 하나여야 한다)
  • 인터페이스의 목적
    • 인터페이스는 스펙을 주어 클래스들이 그 기능을 서로 다르게 구현할 수 있도록 하는 클래스의 규격 선언이며, 클래스의 다형성을 실현하는 도구이다.

예제 5-8 인터페이스 구현

interface PhoneInterface {  //인터페이스 선언
	final int TIMEOUT = 10000;  //상수 필드 선언
	void sendCall();   //추상 메소드 public abstract 가 생략되어있기 떄문에 추상 메소드를 의미
	void receiveCall();   //추상 메소드 
	default void printLogo() {  //default 메소드
		System.out.println("** Phone **");
	}
}
//인터페이스 구현 implements 
class SamsungPhone implements PhoneInterface { 
	// PhoneInterface 의 모든 추상 메소드 구현
    @Override
	public void sendCall() {
		System.out.println("Rrrrrrrr~");
	}
	@Override
	public void receiveCall() {
		System.out.println("You get a phone call.");
	}
	// 추가 메소드 작성
	public void flash() {System.out.println("The phone lights up."); } 	
}

public class InterfaceEx {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SamsungPhone phone = new SamsungPhone(); 
        // SamsungPhone phone = new PhoneInterface(); - > flash 떄문에 사용 불가? 
        // 나랑 관련이 없는 flash 라는 정의가 있기 때문에 오류가 난다 (다시 생각해보기)
		phone.printLogo();
		phone.sendCall();
		phone.receiveCall();
		phone.flash();	
	}
}
//result
// ** Phone **
// Rrrrrrrr~
// You get a phone call.
// The phone lights up.

예제 5-9 : 인터페이스를 구현하고 동시에 클래스를 상속받는 사례

interface PhoneInterface {	//인터페이스 선언
	final int TIMEOUT = 10000;	//상수 필드 선언
	void sendCall();  	//추상 메소드
	void receiveCall(); 	//추상 메소드
	default void printLogo() {	// default 메소드
		System.out.println("** Phone **");
	}
}

// ---'인터페이스'가 다른 '인터페이스' 상속 ---//
// extends 키워드 이용
interface MobilePhoneInterface extends PhoneInterface {
	void sendSMS();   		// 새로운 추상 메소드 추가
	void receiveSMS();		// 새로운 추상 메소드 추가
}

interface MP3Interface {  //인터페이스 선언
	public void play();
	public void stop();
}

class PDA {  //클래스 작성
	public int calculate(int x, int y) {
		return x + y;
	}
}

//SmartPhone 클래스는 PDA 를 상속받고, 
//MobilePhoneInterface 와 MP3Interface 인터페이스에 선언된 추상 메소드를 모두 구현한다.
class SmartPhone extends PDA implements MobilePhoneInterface, MP3Interface {  
	//MobilePhoneInterface의 추상 메소드 구현
    @Override
	public void sendCall() {
		System.out.println("Rrrrrrrr~");
	}
	@Override	
	public void receiveCall() {
		System.out.println("You get a phone call.");
	}
    @Override	
	public void sendSMS() {
		System.out.println("Send a cell phone text.");
	}
    @Override
	public void receiveSMS() {
		System.out.println("I got a cell phone text.");
	}
	
	//MP3Interface의 추상 메소드 구현
    @Override
	public void play() {
		System.out.println("Play music.");
	}
	@Override 
	public void stop() {
		System.out.println("Stop the music.");
	}
	// 추가로 작성한 메소드 
	public void schedule() {
		System.out.println("Manage your calendar.");
	}
}

public class InterfaceExSnd {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SmartPhone phone = new SmartPhone();
		phone.printLogo();
		phone.sendCall();
		phone.play();
		System.out.println("If you add 3 and 5 : " + phone.calculate(3,5));
		phone.schedule();
	}
}
//result
 ** Phone **
Rrrrrrrr~
Play music.
If you add 3 and 5 : 8
Manage your calendar.

추상 클래스와 인터페이스 비교

  • 유사점
    • 객체를 생성할 수 없고, 상속을 위한 슈퍼 클래스로만 사용
    • 클래스의 다형성을 실현하기 위한 목적
  • 다른점
    • 추상 클래스는 일반 메소드와 멤버 변수를 가지며, 구체적인 동작을 하위 클래스에게 위임하는데 사용
    • 인터페이스는 추상 메소드와 상수만을 가지며, 클래스 간의 계약을 정의하고 다형성을 구현하는데 사용
      • 추상메소드, 상수 필드도 아닌 다른 특수 목적의 default, private, static 메소드를 포함한다.
    • 추상 클래스는 상속관계에서 사용되고, 인터페이스는 구현 관계에서 사용
profile
공부한 것 기록용

0개의 댓글