05.02 상속, 다형성,protected 접근 제한자, 추상메소드
매개변수의 다형성을 이용하면 코드를 간결하게 줄일 수 있다.
그리고 기능을 개선할 때 실행클래스는 변경하지 않고 매개변수 교체만 해주면 된다는 장점이 있다.(부품객체관계...)
package extends4_phone_example;
// 1세대 일반 폰
public class Phone {
public String model;
public String color;
public Phone() {
super();
}
public Phone(String model, String color) {
this.model = model;
this.color = color;
}
public void powerOn() {
System.out.println("전원을 켭니다.");
}
public void powerOff() {
System.out.println("전원을 끕니다.");
}
public void bell() {
System.out.println("아날로그 벨소리가 울립니다.");
}
public void pickUp() {
System.out.println("전화를 받습니다.");
}
public void hanUp() {
System.out.println("전화를 끊습니다.");
}
public void sendVoice(String message) {
System.out.println("나 :" + message);
}
public void receiveVoice(String message) {
System.out.println("상대방 : "+ message);
}
}
package extends4_phone_example;
public class DMBPhone extends Phone{
int channel; // 공중파 채널
public DMBPhone(String model, String color, int channel) {
super(model, color);
this.channel = channel;
}
public void turnOnDMB() {
System.out.println("DMB를 켭니다.");
}
public void turnOffDMB() {
System.out.println("DMB를 끕니다.");
}
public void changeChannel(int channel) {
if(channel < 1) {
this.channel = 11;
}else {
this.channel = channel;
}
System.out.println("채널이"+this.channel+"로 변경되었습니다.");
}
}
package extends4_phone_example;
//안드로이드 스마트 폰
public class AndroidPhone extends DMBPhone {
String url;
/*
public AndroidPhone() {
super(); // 기본적으로 부모 생성자 기본 생성자가 생략되어있다.
그런데 DMBPhone의 기본생성자가 없어서 오류 발생함.
}
*/
public AndroidPhone() {
super("DMB","BLUE",1); //명시적으로 부모생성자 생성해줘야함.
}
public AndroidPhone(
String model,
String color,
int channel,
String url) {
super(model, color, channel);
this.url = url;
}
public void turnOnInternet() {
System.out.println("인터넷"+url+"을 켭니다.");
}
public void turnOffInternet() {
System.out.println("인터넷을 끕니다.");
}
public void changeURL(String url) {
this.url = url;
System.out.println(url+"변경 되었습니다.");
}
// @Override
public void bell() {
System.out.println("3D 사운드로 벨소리가 울립니다.");
}
}
package extends4_phone_example;
public class PhoneExample {
public static void main(String[] args) {
Phone phone = new Phone("걸리버","GOLD");
phone.powerOn();
phone.bell();
phone.pickUp();
phone.sendVoice("여보세요.");
phone.receiveVoice("이번에 새로 나온 좋은 상품이 있는데....");
phone.sendVoice("괜찮습니다.");
phone.hanUp();
phone.powerOff();
System.out.println("DMBPhone =====================");
DMBPhone dmbPhone = new DMBPhone("가로본능","SILVER",9);
dmbPhone.powerOn();
dmbPhone.bell();
dmbPhone.pickUp();
dmbPhone.hanUp();
dmbPhone.turnOnDMB();
dmbPhone.changeChannel(12);
dmbPhone.turnOffDMB();
dmbPhone.powerOff();
System.out.println("Android Smart Phone =====================");
AndroidPhone android
= new AndroidPhone("S23","WHITE",1,"http://google.com");
android.powerOn();
android.turnOnDMB();
android.turnOffDMB();
android.turnOnInternet();
android.changeURL("http://naver.com");
android.turnOffInternet();
android.bell();
android.powerOff();
}
}
package extends5_customer;
// 고객 관리를 위해 설계한 클래스
public class Customer {
int customerID; //고객 아이디
String customerName; //고객 이름
String customerGrade; //고객 등급
int bonusPoint; //보너스 포인트
double bonusRatio; //보너스 포인트 적립율
public Customer(int customerID, String customerName) {
this.customerID = customerID;
this.customerName = customerName;
// 고객 등급과 보너스 적립율 초기화
this.customerGrade = "SILVER";
this.bonusRatio = 0.01;
}
//보너스 포인트 적립 후 구매 가격 알림
public int calcPrice(int price) {
bonusPoint += price * bonusRatio;
return price;
}
public String showCustomerInfo() {
return customerName+"님의 등급은 "+customerGrade+"이며 "
+"보너스 포인트는 : " + bonusPoint+"입니다.";
}
}
package extends5_customer;
public class GoldCustomer extends Customer {
double saleRatio; //골드 등급은 할인율 적용
public GoldCustomer(int customerID, String customerName) {
super(customerID, customerName);
super.customerGrade = "GOLD";
super.bonusRatio = 0.02;
this.saleRatio = 0.1;
}
@Override
public int calcPrice(int price) {
bonusPoint += (price * bonusRatio);
return price - (int)(price * saleRatio);
}
}
package extends5_customer;
//할인율이 적용이 되고
//고객을 담당하는 직원이 있는 고객
public class VIPCustomer extends GoldCustomer{
private int agentID; // 담당 직원
public VIPCustomer(int customerID, String customerName, int agentID) {
super(customerID, customerName);
super.customerGrade = "VIP";
super.bonusRatio = 0.05;
super.saleRatio = 0.2;
this.agentID = agentID;
}
@Override
public String showCustomerInfo() {
return super.showCustomerInfo()+" 담당 직원 번호는 :"+this.agentID+"입니다.";
}
}
package extends5_customer;
public class CustomerExample {
public static void main(String[] args) {
Customer[] customerList = new Customer[10];
Customer customerLee = new Customer(100110,"이순신");
Customer customerChoi = new Customer(100111,"최기근");
customerList[0] = customerLee;
customerList[1] = customerChoi;
customerList[2] = new GoldCustomer(201001,"김유신");
Customer vip = new VIPCustomer(301001,"최기근",105098);
customerList[3] = vip;
System.out.println("== 고객 정보 ==");
for(Customer c : customerList) {
if(c != null) {
System.out.println(c.showCustomerInfo());
}
}//고객정보출력 완료
System.out.println("== 보너스 포인트 계산 ==");
int price = 100000;
for(Customer c : customerList) {
if(c!=null) {
int cost = c.calcPrice(price);
System.out.println(c.customerName+"님이 "+cost+"원 지불하셨습니다.");
System.out.println(c.showCustomerInfo());
}
}
}
}
protected 접근 제한자
상속과 관련된 접근 제한자
같은 패키지: default와 동일
다른 패키지: 자식 클래스만 접근 허용
package extends6_protected.a;
public class A {
protected int a;
public int b;
private int c;
protected void methodA() {
System.out.println("A class의 c : " + c);
System.out.println("A class의 methodA 호출");
}
protected final void methodB() {
System.out.println("A class의 methodB 호출");
}
}
package extends6_protected.a;
public final class B {
A a = new A();
public B(){
a.a = 100; //protected
a.b = 100; //public
// a.c = 100; //private 사용x
a.methodA(); //protected
a.methodB(); //protected
}
}
package extends6_protected.b;
import extends6_protected.a.A;
import extends6_protected.a.B;
public class C // extends B // : final class는 설계 수정불가 class - 상속불가
{
//다른 pkg에 있는거 사용시 import
A a = new A();
C(){
//protected : 다른 패키지의 자식 클래스를 제외하고는 접근 불가
// a.a = 100; //protected 사용x
a.b = 100; //public
// a.c = 100; //private 사용x
// a.methodA(); //protected
}
}
package extends6_protected.b;
import extends6_protected.a.A;
public class D extends A{
A a = new A();
D(){
// a.a = 100;
a.b = 200;
// a.c = 300;
// a.methodA();
// a.methodB();
// this.a = 100;
super.a = 100; //protected 접근 시 this 또는 super 사용
methodA();
methodB();
}
@Override
protected void methodA() {
super.methodA();
}
}
final 키워드의 용도
final 필드: 수정 불가 필드
final 클래스: 부모로 사용 불가한 클래스 , "이 클래스가 마지막이다~"
final 메소드: 자식이 재정의할 수 없는 메소드
상속할 수 없는 final 클래스
자식 클래스 만들지 못하도록 final 클래스로 생성
오버라이딩 불가한 final 메소드
자식 클래스가 재정의 못하도록 부모 클래스의 메소드를 final로 생성
추상 클래스(abstract class)
실체 클래스들의 공통되는 필드와 메소드 정의한 클래스
추상 클래스는 실체 클래스의 부모 클래스 역할 (단독 객체 X)
package extends7_abstract;
//추상클래스 - 한개라도 abstract 메소드를 가지고 있으면 추상클래스.
public abstract class Animal {
String kind;
public void breath() {
System.out.println("산소로 호흡합니다.");
}
public abstract void sound();
}
package extends7_abstract;
// 추상클래스를 상속받는 자식클래스는
// 추상클래스 이거나 구현되지 않은 부모의 추상메소드를 구현해야한다.
// public abstract class Cat extends Animal{
public class Cat extends Animal{
@Override
public void sound() {
System.out.println("냐옹");
}
}
package extends7_abstract;
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("멍멍 왈왈!");
}
}
package extends7_abstract;
public class Zoo {
//추상클래스도 다형성 적용 가능하다.
public static void animalSound(Animal animal) {
animal.sound();
}
public static void main(String[] args) {
// Animal animal = new Animal();
Cat cat = new Cat();
cat.kind = "Siamese Cat";
cat.breath();
cat.sound();
Dog dog = new Dog();
dog.kind = "Jindo";
dog.breath();
dog.sound();
animalSound(cat);
animalSound(dog);
Animal navi = new Cat();
navi.kind = "load Cat";
animalSound(navi);
//객체 생성시에 설계정보 재정의(기능만 정의해주면 객체 생성도 가능하다.)
Animal tiger = new Animal() {
@Override
public void sound() {
System.out.println("어흥");
} // 익명 구현 객체 (클래스 없이 수행하는 기능만 정의해서 바로 던지는 객체)
};
tiger.kind = "tiger";
animalSound(tiger);
}
}