과제풀이
원과 다른 세 도형들을 분리시키면 어떨까? 다른 세 도형은 평면도형이니까.
Shape 추상 부모 클래스의 추상메소드를 PlaneShape 자식클래스가 오버라이딩해야하지만, 자식클래스도 추상클래스라면 오버라이딩 안해줘도 괜찮다. 그 자식의 자식들이 오버라이드 하니까.
즉, 추상클래스를 상속받은 추상클래스가 존재할수도 있다.
=> 설계쪽은 디자인패턴 책을 꼭 봐서 따로 공부를 해야된다. 경험으로 얻는거엔 한계가 있다. 영어 잘하면 head first design pattern 원서가 pdf로 돌아다니니 이걸 봐도 된다.
객체 형변환
객체 형변환의 전제조건은 서로 상속관계여야 한다는 것.
[ 명시적 형변환 ]
부모의 값을 갖는 객체가 자식의 주소를 가지게 되는데, 자식의 공간이 부모보다 크기 때문에 불가능. 그래서 강제적으로 형변환을 해주는 것. 부모의 타입을 자식이 가리키는 것. 묵시적 형변환이 되있는 객체만이 명시적 형변환이 가능하다.
[ 묵시적 형변환 ]
Parent p = new Child01();
실제 값은 자식에서 만들어졌지만, 접근 가능한 곳은 부모이다. 하지만 자식에서 오버라이드된 메소드의 경우 주소값이 자식으로 넘어가게되어 자식의 메소드가 실행된다.
인터페이스
- 완벽한 추상화된 객체
- 반쯤 완성된 객체
- 설계도
1. interface 키워드를 이용하여 선언
2. 선언되는 변수는 모두 상수로 적용 (public static final이 생략되있다.)
3. 선언되는 메소드는 모두 추상 메소드로 적용 (public abstract가 생략되있다.)
4. 객체 생성이 불가능 (추상클래스와 동일한 특성)
5. 클래스가 인터페이스를 상속할 경우에는 extends 키워드가 아니라 implements 키워드를 이용
6. 인터페이스를 상속받는 하위클래스는 추상메소드를 반드시 오버라이딩(재정의)해야 한다.
7. 인터페이스 객체변수는 하위클래스를 이용함. (묵시적 형변환)
추상클래스는 멤버변수와 구현된 메소드, 추상메소드 모두를 가질 수 있었다.
또한, 상속은 다중상속이 안되서 A <- B <- C가 한번에 보이는게 아니라
class C extends B {}
class B extends A {}
이렇게 두개로 쪼개져서 상속해야 한다.
근데 실제 회사 업무에서는 이것저것 새로운 기능을 추가해야 할 경우가 생기는데, 다중상속이 안되기 때문에 어렵다.
ex) 복합기
원래는 프린터로 출발했지만 그 외에 팩스, 스캔 등의 역할을 하게된다. 이럴경우 한 클래스가 프린터, 팩스, 스캔 세개의 클래스를 다중상속받아야되는데 불가능하다. 대신, 내용물이 아니라 표준화를 지원해서 다중상속처럼 할 수 있게 하면 되지 않냐? 한 클래스에 옵션처럼 여러 기능들을 붙였다 뗐다 하는것이 “인터페이스”다.
이때는 ‘스캐너가 가진 기능들’, ‘팩스가 가진 기능들’ 이렇게 표준화를 하게되고, 이럴경우 특정한 ‘단위’가 필요하게 된다. 이를 인터페이스라고 하고, 그렇기 때문에 인터페이스는 “추상메소드들의 집합”이다. 멤버변수를 못가진다.
- 인터페이스의 이름은 보통 -able 형태가 많이 붙는다. 어떠어떠한 기능을 가능하게 만들어주기때문에. 하지만 인터페이스는 클래스가 아니고, 고로 인스턴스변수를 만들수 없다.
- 사실 인터페이스와 추상클래스를 구분하는게 쉽지 않다. 둘 다 기능으로만 이뤄진건 같기때문에. 하지만 가장 큰건 인터페이스는 다중상속이 가능하다는 것. 프린터에게 스캐너 인터페이스와 팩스 인터페이스를 상속시킬 수 있기 때문에.
- 인터페이스는 상수 변수만 갖게된다.
interface ServerConstants {
String SERVER_IP = “127.0.0.1”; //=> 사실 public static final String SERVER_IP가 생략되있는것.
}
- 인터페이스는 원래 멤버변수를 못가지지만, 상수변수는 인터페이스당 하나씩 가질 수 있다. 그래서 public static final이 오게된다. 오직 공유되고있는것 하나만 필요하다. setter, getter 또한 만들수 없으니 무조건 public. 이 변수를 접근하려면 ServerConstants.SERVER_IP
- 인터페이스에서 선언되는 메소드는 모두 추상 메소드로 적용된다.
=> 다중상속의 문제는 상속받는 두 부모클래스에 같은 이름의 메소드가 있으면 자식클래스에서는 어떤 애의 메소드를 호출하는지 알수가 없음.
인터페이스는 다중상속을 하면서 이를 방지하기위해 모든 메소드를 추상메소드로 선언한다. 인터페이스를 상속받는 클래스에서 직접 구현하도록 하기 위해.
이렇게 인터페이스는 혼자선 암것도 할수없으나, 인터페이스의 강점은 ‘다형성’이다. 추상클래스를 오버라이딩하며 서로 다른 클래스가 같은 이름의 메소드로 다른 결과를 표현할 수 있다.
But, 재정의할때 중요한점
ex)
interface Printer {
void print();
}
class LGPrinter implements Printer{
public void print() {
//=> 인터페이스 메소드엔 public abstract가 생략되있으므로 자식클래스에도 public을 선언해줘야한다.
system.out.println(“재정의”);
}
}
인터페이스 객체변수는 하위클래스를 이용함.
interface Printer {}
class LGPrinter implements Printer {}
class Main {
public static void main(String[] args) {
Printer p = new LGPrinter();
}
}
인터페이스가 더 상위의 인터페이스를 상속받을수도 있는데, 이땐 implements가 아니라 extends이고, 인터페이스는 한번에 하나의 인터페이스를 상속받을 수 있다.
cf) final은 상수뿐만아니라 클래스나 메소드에도 붙을수있다.
실습 코드 및 과제
https://github.com/LeenaKim/Java_Lessons/tree/master/src/kr/ac/kopo/day09
'Programming > Java' 카테고리의 다른 글
[ JAVA 수업 DAY 12 ] jar 파일 활용, Collection (0) | 2020.05.05 |
---|---|
[ JAVA 수업 DAY 10 - 11 ] Final, 인터페이스+, 예외처리, Java API (0) | 2020.05.05 |
[ JAVA 수업 DAY 07 - 08 ] 상속, 추상클래스, 객체형변환 (0) | 2020.05.05 |
[ JAVA 수업 DAY 06 ] 문자열 (0) | 2020.05.05 |
[ JAVA 수업 DAY 05 ] 클래스와 메소드 (0) | 2020.05.05 |