다형성 장단점
- 장점 : 코드가 압도적으로 감소한다
확장성이 좋아지고 결합이 약해진다
후반부로 갈 수록 많이 나오는 기술
- 단점 : 어렵다
전제조건이 까다롭다 (1. 상속, 2. 재정의)
오류가 발생한 경우 추적이 어렵다
다중상속과 인터페이스
자바의 절대 규칙 : 클래스는 단 하나만 상속이 가능하다.
왜? 모호한 상황이 생기기 때문에!
그렇다고 다중상속이 필요없다고 생각하는것은 아니다
다중상속은 반드시 필요하지만 오류의 가능성(ex:모호성)이 매우 높은 방법
-> 인터페이스는 다중상속이 가능하다
클래스는 최대 1개의 클래스와 무제한 개수의 인터페이스 상속이 가능하다
인터페이스는 implements 키워드로 상속받는다
Q. 인터페이스 구현 방법보기
package oop.multi3;
public interface Phone {
void camera();
void gallery();
void call();
void sms();
}
package oop.multi3;
public class Galaxy21s implements Phone {
@Override
public void camera() {
}
@Override
public void gallery() {
}
@Override
public void call() {
}
@Override
public void sms() {
}
}
인터페이스의 구조
인터페이스도 클래스의 한 종류이다.
클래스의 구성요소들 중 가질 수 있는 것과 없는 것이 있다.
다중상속에서의 부모 클래스가 목적이기 때문에 "모호함"을 발생시키는 요소들이 전부다 제거되었다.
결론 : 인터페이스는 "상수"와 "추상메소드"를 가질 수 있다.
package oop.multi3;
public interface sample {
// 멤버 변수 : 생성 불가. 오로지 상수만 정의할 수 있다. 안써도 자동생성
public static final int a = 10;
/* public static final */ int b = 20; // 안써도 자동 생성
// 멤버 메소드 : 일반 메소드는 불가. 추상 메소드만 가능. 안써도 자동생성
/* public abstract */ void showInfo(); // 안써도 자동 생성
// 생성자 : 생성자는 가질 수 없다(super 사용 방지 차원)
// public Sample(){}
}
Q . 예제로 다중상속 풀이
대형 생필품 매장에서 제품들을 관리하기 위해 클래스 시스템을 구축하려 합니다.
- 관리할 제품들은 다음과 같습니다.
- 컴퓨터(Computer)
- 빵(Bread)
- 정리용 바구니(Basket)
- 우유(Milk)
- 유리접시(Dish)
- 제품들은 각각 다음과 같은 핵심 기준에 의해서 분류됩니다.(단 한 가지의 특성만 적용이 가능합니다)
- 전자제품(Electronic) : 전기에 의해서 구동되는 물건들을 말하며 이름을 설정할 수 있고 전원 관련 기능(on, off)를 가지고 있습니다.
- 식료품(Grocery) : 먹을 수 있는 제품들을 말하며 이름과 유통기한을 설정할 수 있습니다.
- 생활용품(Household) : 일상생활에 필요한 용품들을 말하며 이름을 설정할 수 있습니다.
- 제품들은 각각 다음과 같은 기준에 의해서 추가 분류됩니다.
- 깨질 수 있는 제품(Brokenable) : 충격을 받으면 깨질 수 있는 형태의 물건을 의미하며 따로 기능은 존재하지 않습니다.
- 액체 상품(Liquid) : 액체 형태의 물건을 의미하며 따로 기능은 존재하지 않습니다.
상위부터 하위로 구현하기
package oop.multi5;
public abstract class Product {
protected String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Product(String name) {
this.setName(name);
}
}
<대분류>
package oop.multi5;
public abstract class Electronic extends Product {
public Electronic(String name) {
super(name);
}
public abstract void on();
public abstract void off();
}
package oop.multi5;
public abstract class Grocery extends Product {
protected String expire;
public void setExpire(String expire) {
this.expire = expire;
}
public String getExpire() {
return expire;
}
public Grocery(String name, String expire) {
super(name);
this.setExpire(expire);
}
}
package oop.multi5;
public abstract class Household extends Product {
public Household(String name) {
super(name);
}
}
<Marking interface>
오직 검사만을 위해 만드는 인터페이스
기능이 하나도 없음
package oop.multi5;
public interface Brokenable {
}
package oop.multi5;
public interface Liquid {
}
<제품 종류>
package oop.multi5;
public class Computer extends Electronic implements Brokenable {
public Computer(String name) {
super(name);
}
@Override
public void on() {
System.out.println(this.name + " 전원이 켜집니다");
}
@Override
public void off() {
System.out.println(this.name + " 전원이 꺼집니다");
}
}
package oop.multi5;
public class Bread extends Grocery{
public Bread(String name, String expire) {
super(name, expire);
}
}
package oop.multi5;
public class Basket extends Household implements Brokenable {
public Basket(String name) {
super(name);
}
}
package oop.multi5;
public class Milk extends Grocery implements Liquid {
public Milk(String name, String expire) {
super(name, expire);
}
}
package oop.multi5;
public class Dish extends Household implements Brokenable {
public Dish(String name) {
super(name);
}
}
<기능이 들어있는 Computer만 실행해보기>
package oop.multi5;
public class Test01 {
public static void main(String[] args) {
Computer com = new Computer("슈퍼컴퓨터");
com.on();
com.off();
}
}
- 정답
슈퍼컴퓨터 전원이 켜집니다
슈퍼컴퓨터 전원이 꺼집니다
Q. 추가 문제
- 각각의 유형별 제품을 담을 수 있는 다음 형태의 클래스를 만들고 객체를 생성해보세요
- ElectronicBox : 전자제품 1개를 보관할 수 있는 상자
- GroceryBox : 식료품 1개를 보관할 수 있는 상자
- HouseholdBox : 생활용품 1개를 보관할 수 있는 상자
- SafeBox : 파손 가능한 상품을 1개 안전하게 보관할 수 있는 상자
- LiquidBox : 액체 상품을 1개 보관할 수 있는 상자
메인에서 각각의 종류별 상자를 만드시고, 상자에 들어갈 제품을 생성해서 상자에 집어넣어 보세요
문제가 어렵게 느껴지면 이해하기 쉽게 접근해보자
공통점이 '1개' 보관이다
전자제품말고 정수를 '1개' 보관으로 생각해보면 어떨까?
package oop.multi5;
//정수 1개를 보관할 수 있는 상자
public class IntBox {
private int value;
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
-->> 전자제품으로 바꿔보자
package oop.multi5;
//전자제품(Electronic) 1개 저장 클래스
public class ElectronicBox {
private Electronic value;
public void setValue(Electronic value) {
this.value = value;
}
public Electronic getValue() {
return this.value;
}
}
-->> 나머지도 똑같이 만들어 준다
<결과>
업캐스팅이라는걸 알수 수 있다.
package oop.multi5;
public class Test02 {
public static void main(String[] args) {
IntBox box1 = new IntBox();
box1.setValue(100);
System.out.println(box1.getValue());
ElectronicBox box3 = new ElectronicBox();
Computer c = new Computer("슈퍼컴퓨터");
box3.setValue(c);
System.out.println(box3.getValue());
box3.getValue().on();
box3.getValue().off();
}
}
제네릭(Generic) 클래스 가볍게 알아가기
내가 직접 저장할 형태를 작성해가면서 사용할 수 있는 상자
클래스 옆에다가 <> 를 적고 사이에 이름을 적으면 해당하는 이름을 자료형 처럼 사용 가능
AllInOneBox<E> 라고 적으면 E 라는 미지의 자료형의 데이터를 저장할 수 있는 상자
Generic class(제네릭 클래스)라고 한다
all-in-one-box의 사용법
package oop.multi6;
public class AllInOneBox<E> {
private E value;
public void setValue(E value) {
this.value = value;
}
public E getValue() {
return this.value;
}
}
package oop.multi6;
public class Test01 {
public static void main(String[] args) {
// AllInOneBox의 E를 String으로 설정하여 생성
AllInOneBox<String> box1 = new AllInOneBox<String>();
box1.setValue("hello");
System.out.println(box1.getValue());
}
}
중첩 클래스
일반 중첩 클래스 활용 예시경찰, 강도, 총으로 알아보자
package oop.inner1;
public class Gun {
}
package oop.inner1;
public class Police {
private Gun gun;
public Gun getGun() {
return gun;
}
public void setGun(Gun gun) {
this.gun = gun;
}
}
package oop.inner1;
public class Robber {
private Gun gun;
public Gun getGun() {
return gun;
}
public void setGun(Gun gun) {
this.gun = gun;
}
}
--> 이렇게 총을 경찰도 가지고, 강도도 가질 수 있다
만약 권총을 경찰만 소지하도록 하고 싶다면 클래스 구성을 어떻게 해야할까?
대략 다음과 같은 방법들이 있을 것이다.
package oop.inner2;
public class Police { // 외부 클래스
private Gun gun;
public Gun getGun() {
return gun;
}
public void setGun(Gun gun) {
this.gun = gun;
}
// 경찰만이 권총을 사용할 수 있도록
// = 경찰 클래스 내부에 권총 클래스를 구현
// = 경찰 외부에서는 Gun이 있느지 알 수 없음
private class Gun { //내부or 중첩 클래스
// 클래스이므로 이 안에 구성요소를 모두 가질 것
// = 멤버 변수, 메소드, 생성자, 중첩클래스
}
}
package oop.inner2;
public class Robber {
//아래 코드들은 모두 오류가 발생한다.
// private Gun gun;
//
// public Gun getGun() {
// return gun;
// }
//
// public void setGun(Gun gun) {
// this.gun = gun;
// }
}
★★★★★★★★★★
★익명 중첩 클래스 ★
★★★★★★★★★★
package oop.inner3;
public abstract class Button {
public abstract void push();
}
package oop.inner3;
public class MenuButton extends Button {
@Override
public void push() {
System.out.println("메뉴를 표시합니다");
}
}
package oop.inner3;
public class ExitButton extends Button {
@Override
public void push() {
System.out.println("프로그램을 종료합니다");
}
}
package oop.inner3;
public class Test01 {
public static void main(String[] args) {
MenuButton button1 = new MenuButton();
button1.push();
ExitButton button2 = new ExitButton();
button2.push();
}
}
메뉴를 표시합니다
프로그램을 종료합니다
--> 단 하나의 객체를 위해 클래스를 만드는게 사치다 - 비효율적
익명 중첩 클래스(anonymous inner class)
버튼을 그때그때 상속받아서 서로 다른 기능을 가지도록 구현하자! (일회용개념)
클래스의 몸통만 가져와서 객체 생성시 즉석에서 상속 및 수정하도록 구현하는 방식
일회용 코드를 작성하기 편리하다
상속이 불가능한 클래스(final class)는 생성 불가
추상 클래스, 인터페이스 객체도 생성 가능(상속하므로)
package oop.inner3;
public class Test02 {
public static void main(String[] args) {
Button button1 = new Button() {
@Override
public void push() {
System.out.println("메뉴를 표시합니다");
}
};
button1.push();
// Q : 종료버튼을 button2 라는 이름으로 생성해보세요
Button button2 = new Button() {
@Override
public void push() {
System.out.println("프로그램을 종료합니다");
}
};
button2.push();
}
}
메뉴를 표시합니다
프로그램을 종료합니다
'Java 웹 개발' 카테고리의 다른 글
21.09.07 - 웹 개발 입문 20일차 (0) | 2021.09.07 |
---|---|
21.09.06 - 웹 개발 입문 19일차 (0) | 2021.09.06 |
21.09.02 - 웹 개발 입문 17일차 (0) | 2021.09.02 |
21.09.01 - 웹 개발 입문 16일차 (0) | 2021.09.01 |
21.08.31 - 웹 개발 입문 15일차 (0) | 2021.08.31 |