



부모클래스 beverage
package oop.inheritance;
public class Beverage {
private String type;
private int price;
public Beverage(String type, int price) {
super();
this.type = type;
this.price = price;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
자식클래스 coffee
package oop.inheritance;
public class Coffee extends Beverage {
private String name;
public Coffee(String type, int price, String name) {
super(type, price);
this.name = name;
}
public void print() {
System.out.println("타입:"+getType()+", "+"가격: "+getPrice()+", "+"이름: "+name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}



부모클래스 Account
package oop.inheritance;
public class Account {
private String accId;
private long balance;
private String ownerName;
public Account() {
}
public Account(String accId, long balance, String ownerName) {
super();
this.accId = accId;
this.balance = balance;
this.ownerName = ownerName;
}
//입금하기
public void deposit(long amount) {
balance = balance + amount;
}
//출금하기
public void withdraw(long amount) {
balance = balance - amount;
}
public String getAccId() {
return accId;
}
public void setAccId(String accId) {
this.accId = accId;
}
public long getBalance() {
return balance;
}
public void setBalance(long balance) {
this.balance = balance;
}
public String getOwnerName() {
return ownerName;
}
public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}
}
자식클래스 checkingAccount
package oop.inheritance;
public class CheckingAccount extends Account {
private String cardNo;
public CheckingAccount() {
}
public CheckingAccount(String accId, long balance, String ownerName,String cardNo) {
super(accId,balance,ownerName);
this.cardNo = cardNo;
}
public void pay(long amount,String cardNo) {
//String은 참조형이니까 ==은 주소 비교하는것
//문자열을 비교하는 경우 무조건 equals=>대소문자까지 비교
if(amount<=getBalance() & this.cardNo.equals(cardNo)) {
withdraw(amount);
}
else{
System.out.println("지불이 불가능합니다.");
}
}
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
}
Drink 클래스의 제약조건
1. 상품명(name), 단가(price), 수량(count) 정보를 저장하는 멤버변수가 있어야 한다.
3. 멤버변수를 초기화하는 생성자 메서드가 있어야 한다.
4. 금액(단가*수량)을 계산하는 getTotalPrice() 메서드가 있어야 한다.
5. 타이틀을 출력하는 printTitle() 메서드가 있어야 한다.
5. 상품의 정보를 출력하는 printData() 메서드가 있어야 한다.
Alcohol 클래스의 제약조건
1. Drink 클래스를 상속받아야 한다.
2. 알코올 도수를 나타내는 멤버변수(alcper)가 있어야 한다.
3. 멤버변수를 초기화하는 생성자 메서드가 있어야 한다.
4. 부모 클래스인 Drink 의 printTitle() 메서드의 기능을 재정의(오버라이딩) 한다.
5. 부모 클래스인 Drink 의 printData() 메서드의 기능을 재정의(오버라이딩) 한다.

상위클래스 Drink
package oop.inheritance;
public class Drink {
private String name;
private int price;
private int count;
public Drink() {
}
public Drink(String name, int price, int count) {
super();
this.name = name;
this.price = price;
this.count = count;
}
public int getTotalPrice() {
int totalPrice = 0;
totalPrice = price * count;
return totalPrice;
//return count*price;//이렇게해도됨!
}
public static void printTitle() {
System.out.println("상품명\t단가\t수량\t금액");
}
public void printData() {
System.out.println(name+"\t"+price+"\t"+count+"\t"+getTotalPrice());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
하위클래스 Alcohol
package oop.inheritance;
public class Alcohol extends Drink{
private double alcper;
public Alcohol() {
}
//상위클래스 상속 표시(?)도 generate using field-insert point에서 설정해서 만들수있음.
public Alcohol(String name, int price, int count,double alcper) {
super(name,price,count);
this.alcper = alcper;
}
public static void printTitle() {
System.out.println("상품명(도수[%])\t단가\t수량\t금액");
}
public void printData() {
System.out.println(getName()+"("+alcper+")"+"\t"+getPrice()+"\t"+getCount()+"\t"+getTotalPrice());
}
public double getAlcper() {
return alcper;
}
public void setAlcper(double alcper) {
this.alcper = alcper;
}
}
package oop.polymorphism;
class Vehicle {
//has a 관계
Tire tire;//null상태
//Tire tire2 = new Tire();//Tire객체를 참조하고 있는 상태, has a 관계라서 이렇게 정의하지않음
public Vehicle() {}
public Vehicle(Tire tire) {
super();
this.tire = tire;
}
public void run() {
System.out.println("차량이 달립니다.");
}
}
class Bus extends Vehicle{
//Source - Override/Implement method하면 생성됨
@Override
public void run() {
System.out.println("버스가 달립니다.");
}
}
class Taxi extends Vehicle{
@Override
public void run() {
System.out.println("택시가 달립니다.");
}
}
public class VehicleTest{
public static void main(String[] args) {
Bus obj = new Bus();
obj.tire = new HankookTire();
Taxi obj2 = new Taxi();
obj2.tire = new KumhoTire();
obj.run();
obj2.run();
}
}
package oop.polymorphism;
class HankookTire extends Tire{
@Override
public void roll() {
System.out.println("한국타이어가 회전합니다.");
}
}
class KumhoTire extends Tire{
@Override
public void roll() {
System.out.println("금호타이어가 회전합니다.");
}
}
public class Tire {
//메소드
public void roll() {
System.out.println("차량이 달립니다.");
}
}
final을 붙이면 어떻게 되는지(교재 345p)
package oop.inheritance;
final class A{
public void test() {
//일반기능의 메소드 - 하위클래스에서 상속해서 변경해야하는 메소드
}
public final void login(String pass) {
System.out.println("부모클래스의 중요한 메소드 - 인증하고 엑세스하기");
}
}
class B extends A{//상속불가. A가 final class라서
public void login(String pass) {//오버라이딩 불가. login이 final method라서
System.out.println("인증하지 않고 엑세스하는 코드로 수정");
}
}
public class FinalTest {
public static final int CODE=100;//상수는 대문자로, final이붙는 상수 앞엔 static이 붙음.
public void test() {
//CODE = 1000; 상수는 값을 재할당할 수 없다.
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
: 객체를 생성할 수 없는 클래스, 미완성된 클래스
: 내용이 구현되어있지 않은 메소드(추상메소드 : body가 없는 메소드)를 포함하고 있는 클래스를 추상클래스라 한다.
1) 추상메소드를 선언하는 방법
접근제어자 abstract 리턴타입 메소드명(매개변수1,매개변수2...);
2) 추상클래스의 특징
package oop.polymorphism;
abstract class Parent{//추상클래스
public void test() {
System.out.println("일반메소드");
}
public abstract void display(String data);//추상메소드
}
class Child extends Parent{
//컴파일러에 정보를 알려주는 작업
//@Override는 컴파일러에게 오버라이딩된 메소드라는 것을 알려주는 기호
@Override
public void display(String data) {
System.out.println("부모에게 상속받은 추상메소드를 구현");
}
}
public class AbstractTest {
public static void main(String[] args) {
Child obj = new Child();
obj.display("");
}
}
출력 :
부모에게 상속받은 추상메소드를 구현
package oop.polymorphism;
import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
public class RefTypeCastingTest {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
AbstractList<String> ablist = new ArrayList<String>();
AbstractCollection<String> aclist = new ArrayList<>();
List<String> list2 = new ArrayList<>();
String str = new String("java");
StringBuffer sb = new StringBuffer();
//String = StringBuffer
//참조형에서 상속관계가 아닌 경우에는 캐스팅을 할 수 없다.
//참조형에서 캐스팅을 하려면 무조건 상속관계에 있는 클래스여야 함
//str = sb;//컴파일 오류
}
}
package oop.polymorphism;
//객체의 형변환
//사용자정의클래스
class Super{
String data = "상위클래스";
public void display() {
System.out.println("super의 display");
}
}
class Sub extends Super{
String data = "하위클래스";
public void display() {
System.out.println("sub의 display");
}
public void test() {
System.out.println("sub의 test");
}
}
//sub가 자식객체지만 부모객체 super보다 확장된 영역임을 기억하며 보기..
public class RefTypeCastingTest2 {
public static void main(String[] args) {
System.out.println("1.Super타입의 참조변수로 Super객체를 사용");
Super obj1 = new Super();
obj1.display();
System.out.println(obj1.data);
System.out.println("***************************************");
System.out.println("2.Sub타입의 참조변수로 Sub객체를 사용");
Sub obj2 = new Sub();
obj2.display();
System.out.println(obj2.data);
System.out.println("***************************************");
//상속관계에 있는 클래스는 자동캐스팅
//서브클래스의 인스턴스를 슈퍼클래스타입으로 변환하는 작업 - 업캐스팅(안전) : 할당되는 자식타입이 부모타입화되는게 업캐스팅
//컴파일 시점과 런타임 시점의 차이때문에 테스트 실행안됨
//컴파일시점에는 참조변수의 타입에 따라서 사용 가능한 멤버가 결정된다.
//자바는 동적바인딩을 해서 객체 관리
//동적바인딩 : 런타임시에 실제 생성되는 객체를 확인하고 메소드의 실행도 실제 생성되는 객체의 메소드가 실행
//필드(멤버변수)는 참조변수의 선언된 타입으로 호출되고
//메소드는 런타임시에 실제 할당된 객체의 메소드가 호출
//즉 참조변수가 참조하는 실제 힙에 할당된 객체 타입을 보고 실행
System.out.println("3.Super타입의 참조변수로 Sub객체를 사용");
Super obj3 = new Sub();
obj3.display(); //얘는 왜 오버라이딩 된 결과가 나오냐?
//obj3.test();
//obj3이 Super타입의 참조변수이지만 실제 참조하고있는 생성된 객체는 Sub 객체이므로 캐스팅이 가능
//부모타입인 obj3의 객체참조를 서브객체참조로 변환 => 다운캐스팅
((Sub)obj3).test();//obj3이 실제로 참고하는 객체가 서브기때문에 넘어감
System.out.println(obj3.data);
System.out.println(((Sub)obj3).data);//멤버변수는 얘 클래스가 타입이 어떻게되냐에 따라 결정..?
System.out.println("***************************************");
//캐스팅이 안된다고 하기 보다는 인식을 할 수 없는 거죠 이미 부모타입으로 캐스팅이 된 상태라 안 보이는 상태인거죠
System.out.println("4.Sub타입의 참조변수로 Super객체를 사용");
//Sub obj4 = new Super(); 불가능함~!
System.out.println("***************************************");
//명시적으로 캐스팅하면 컴파일러를 속일 수 있다.
//but 실행시엔ㄴ obj1이 참조하는 객체가 Super이므로 실행할 때 캐스팅을 할 수 없어 오류가 발생한다.
System.out.println("5. Sub변수 = Super객체를 참조하는 변수");
//Sub obj5 = (Sub)obj1;//얘는 실제로 수퍼이기 때문에 오류, 불가능함~!
System.out.println("***************************************");
System.out.println("6.Sub변수 = Sub객체를 참조하는 Super변수가 오는경우");
Sub obj6 = (Sub)obj3;
obj6.display();
System.out.println(obj6.data);
}
}
출력:
1.Super타입의 참조변수로 Super객체를 사용
super의 display
상위클래스
2.Sub타입의 참조변수로 Sub객체를 사용
sub의 display
하위클래스
3.Super타입의 참조변수로 Sub객체를 사용
sub의 display
sub의 test
상위클래스
하위클래스
4.Sub타입의 참조변수로 Super객체를 사용
6.Sub변수 = Sub객체를 참조하는 Super변수가 오는경우
sub의 display
하위클래스
package oop.polymorphism;
abstract class ParentA{
public abstract void print();
}
//상위클래스로 쓰기위한 목적으로 만듦. 바디는 필요없음. 실행시점에 오버라이딩하기위해,,?
//추상클래스를 정의하는 목적 자체가 컴파일러가 프린트메소드를 인식하게 만들고, 어차피 실행시점엔 하위클래스에서 오버라이딩된게 실행됨
class ChildB extends ParentA{
public void print() {
System.out.println("ChildB");
}
}
class ChildC extends ParentA{
public void print() {
System.out.println("ChildC");
}
}
class ChildD extends ParentA{
public void print() {
System.out.println("ChildD");
}
}
class NewChild extends ParentA{
public void print() {
System.out.println("NewChild");
}
}
public class PolyTest {
public static void main(String[] args) {
// ChildB obj = new ChildC(); //캐스팅은 부모자식간의 관계(상속관계)만 가능
ParentA obj = new ChildB();
ParentA obj2 = new ChildC();
ParentA obj3 = new ChildD();
ParentA obj4 = new NewChild();
test(obj4);
}
public static void test(ParentA obj) {//super타입의 변수로는 모든 하위객체를 다 받을 수 있음
obj.print();
}
}
본 포스팅은 멀티캠퍼스의 멀티잇 백엔드 개발(Java)의 교육을 수강하고 작성되었습니다.