@Override
를 적어주면 좋다. 다른 사람들도 인식할 수 있기 때문이다.에스프레소 맛이 쓰다
package ex01_override;
public class Coffee {
// 커피 원두를 의미함
public void taste() {
}
}
package ex01_override;
public class Espresso extends Coffee {
// 메소드 오버라이딩
// 유일한 규칙은 똑같은 모양으로 만들면 된다.
// 권장 규칙은 @Override 추가
@Override
public void taste() {
System.out.println("쓰다");
}
}
package ex01_override;
public class EspressoMain {
public static void main(String[] args) {
Espresso espresso = new Espresso();
espresso.taste(); // 쓰다
}
}
에스프레소에 extraWater를 추가하면 Americano
에스프레소에 extraMilk를 추가하면 CafeLatte
package ex01_override;
public class Americano extends Espresso {
private int extraWater;
@Override
public void taste() {
System.out.println("덜쓰다");
}
}
package ex01_override;
public class CafeLatte extends Espresso {
private int extraMilk;
@Override
public void taste() {
System.out.println("부드럽다");
}
}
package ex01_override;
public class EspressoMain {
public static void main(String[] args) {
Espresso espresso = new Espresso();
espresso.taste(); // 쓰다
Americano americano = new Americano();
americano.taste(); // 덜쓰다
CafeLatte cafeLatte = new CafeLatte();
cafeLatte.taste(); // 부드럽다
}
}
도형의 종류
package ex02_override;
public class Shape {
private String type; // 도형의 종류
public Shape(String type) {
super(); // 신경쓰지 않는다.
this.type = type;
}
public double getArea() {
return 0;
}
public void info() {
System.out.println("도형의 종류 : " + type);
}
}
package ex02_override;
public class Circle extends Shape {
private double radius;
public Circle(String type, double radius) {
super(type);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * Math.pow(radius, 2);
}
@Override
public void info() {
super.info();
System.out.println("반지름 : " + radius);
System.out.println("넓이 : " + getArea());
}
}
package ex02_override;
public class Main {
public static void main(String[] args) {
Circle circle = new Circle("도넛", 7.5);
circle.info();
// 도형의 종류 : 도넛
} // 반지름 : 7.5
} // 넓이 : 176.71458676442586
너비, 높이를 가지는 사각형(Rectangle)
너비, 높이를 서로 같은 정사각형(Square)
package ex02_override;
public class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(String type, double width, double height) {
super(type);
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return width * height;
}
@Override
public void info() {
super.info();
System.out.println("너비 : " + width + " / " + "높이 : " + height);
System.out.println("넓이 : " + getArea());
}
}
package ex01_override;
public class Square extends Rectangle{
public Square(String type, double width) {
super(type, width, width);
}
}
Override 대상이 아니라서 만들지 않고, Rectangle
것을 그대로 사용한다.
package ex02_override;
public class Main {
public static void main(String[] args) {
Circle circle = new Circle("도넛", 7.5);
circle.info();
Rectangle rectangle = new Rectangle("사각형", 5, 7);
rectangle.info();
Square square = new Square("정사각형", 5);
square.info();
}
}
반환값
도형의 종류 : 도넛
반지름 : 7.5
넓이 : 176.71458676442586
도형의 종류 : 사각형
너비 : 5.0 / 높이 : 7.0
넓이 : 35.0
도형의 종류 : 정사각형
너비 : 5.0 / 높이 : 5.0
넓이 : 25.0
Coffee - Espresso - Americano 상속
Espresso 케냐 원두, 물 50ml
Americano 케냐 원두, 물 300ml, 아이스 아메리카노
package quiz01_coffee;
public class Coffee {
private String origin;
public Coffee(String origin) {
super();
this.origin = origin;
}
public void info() {
System.out.println(origin + "원두");
}
}
package quiz01_coffee;
public class Espresso extends Coffee {
private int water;
public Espresso(String origin, int water) {
super(origin);
this.water = water;
}
@Override
public void info() {
super.info();
System.out.println("물 " + water + "ml");
}
}
package quiz01_coffee;
public class Americano extends Espresso {
private String type;
public Americano(String origin, int water, String type) {
super(origin, water);
this.type = type;
}
@Override
public void info() {
super.info();
System.out.println(type + " 아메리카노");
}
}
package quiz01_coffee;
public class Main {
public static void main(String[] args) {
Espresso espresso = new Espresso("케냐", 50);
espresso.info(); // 케냐 원두, 물 50ml
Americano americano = new Americano("케냐", 300, "아이스");
americano.info(); // 케냐 원두, 물 300ml, 아이스 아메리카노
}
}
반환값
케냐원두
물 50ml
케냐원두
물 300ml
아이스 아메리카노
Coffee - Espresso 상속, Americano는 Espresso 상속이 아닌 포함하는 형태로
Espresso 케냐 원두, 물 50ml
Americano 케냐 원두, 물 50ml 2샷, 아이스 아메리카노
package quiz02_coffee;
public class Coffee {
private String origin;
public Coffee(String origin) {
super();
this.origin = origin;
}
public void info() {
System.out.println(origin + "원두");
}
}
package quiz02_coffee;
public class Espresso extends Coffee {
private int water;
public Espresso(String origin, int water) {
super(origin);
this.water = water;
}
@Override
public void info() {
super.info();
System.out.println("물 " + water + "ml");
}
}
package quiz02_coffee;
public class Americano {
private Espresso espresso;
private int shot;
private String type;
public Americano(Espresso espresso, int shot, String type) {
super();
this.espresso = espresso;
this.shot = shot;
this.type = type;
}
public void info() {
espresso.info();
System.out.println(shot + "샷");
System.out.println(type + " 아메리카노");
}
}
package quiz02_coffee;
public class Main {
public static void main(String[] args) {
Espresso espresso = new Espresso("케냐", 50);
espresso.info(); // 케냐 원두, 물 50ml
Americano americano = new Americano(espresso, 2, "아이스");
americano.info(); // 케냐 원두, 물 50ml 2샷, 아이스 아메리카노
}
}
반환값
케냐원두
물 50ml
케냐원두
물 50ml
2샷
아이스 아메리카노
요금을낸다( )
와 벨을누른다( )
는 호출용이고, 실제로는 서브클래스 Bus에 있는 것으로 실행한다.package ex01_upcasting;
public class Person {
public void eat() {
System.out.println("먹는다.");
}
// Person 타입의 객체가 호출할 수 있도록 추가해 둔 메소드
public void study() {}
public void work() {}
}
package ex01_upcasting;
public class Student extends Person {
@Override
public void study() {
System.out.println("공부한다.");
}
}
package ex01_upcasting;
public class Alba extends Student {
@Override
public void work() {
System.out.println("일한다.");
}
}
UpCasting
슈퍼클래스 객체 = new 서브클래스( );
package ex01_upcasting;
public class Main {
public static void main(String[] args) {
Person alba = new Alba();
alba.eat(); // 먹는다
alba.study(); // 공부한다
alba.work(); // 일한다
new Student( )와 new Alba( )는 모두 Person 타입으로 처리할 수 있다.
한 교실에 Student와 Alba가 섞여 있다.
어떻게 처리할 것인가?
Person 타입의 배열을 이용해서 모두 처리할 수 있다.
Person[] people = new Person[10];
people[0] = new Alba(); // 먹,공,알
people[1] = new Alba(); // 먹,공,알
people[2] = new Student(); // 먹,공
// 이렇게 사용하면 안된다.
// WHY? 배열 값을 3개만 작성했기 때문에 나머지는 null값이다.
// 일반 for문
for(int i = 0; i < people.length; i++) {
if(people[i] != null) {
people[i].eat();
people[i].study();
people[i].work();
}
}
// 향상 for문
for(Person person : people) {
if(person != null) {
person.eat();
person.study();
person.work();
}
}
}
}
좌석 앉기
package quiz03_bus;
public class Person {
private String name;
public Person(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package quiz03_bus;
public class Student extends Person {
public Student(String name) {
super(name);
}
}
package quiz03_bus;
public class Alba extends Student {
public Alba(String name) {
super(name);
}
}
package quiz03_bus;
public class Seat {
// Person, Student, Alba를 모두 저장할 수 있는 타입은 Person
private Person person;
// Seat 생성자를 생략하면
// public Seat( ) { } → 디폴트 생성자가 사용됨
// new Seat( )를 이용한 시트 생성이 가능함
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
package quiz03_bus;
public class Bus {
private Seat[] seats; // 배열 선언
private int limit; // 버스 정원
// Bus 생성자에서 배열 생성을 진행함
public Bus(int cnt) {
seats = new Seat[cnt]; // 배열 생성, new Bus(25)인 경우 Seat가 25개 생성됨
limit = cnt;
for(int i = 0; i < cnt; i++) {
seats[i] = new Seat();
}
}
// ride( ) 메소드
public void ride(int seatNo, Person person) {
// 존재하지 않는 시트번호
if(seatNo <= 0 || seatNo > limit) {
return; // ride( ) 매소드 종료
}
// 시트에 사람이 없으면, 시트번호에 Person 저장하기
Seat seat = seats[seatNo - 1];
Person p = seat.getPerson();
if(p == null) {
seat.setPerson(person);
}
}
// info( ) 메소드
public void info() {
for(int i = 0; i < limit; i++) { // limit은 seats 배열의 length와 같음
Seat seat = seats[i];
Person person = seat.getPerson(); // Person person = seats[i].getPerson();
if(person != null) { // if(seat.getPerson() != null), if(seats[i].getPerson() != null)
System.out.println((i + 1) + "," + person.getName());
// System.out.println((i + 1) + "," + seat.getPerson().getName());
// System.out.println((i + 1) + "," + seats[i].getPerson().getName());
} else {
System.out.println((i + 1) + ", 비어 있음");
}
}
}
}
1번째 좌석에 김씨 사람
이 타고, 5번째 좌석에 최씨 학생
이 타고, 10번째 좌석에 민씨 알바
가 탔다.
package quiz03_bus;
public class Main {
public static void main(String[] args) {
Bus bus = new Bus(25);
bus.ride(1, new Person("kim"));
bus.ride(1, new Person("lee"));
bus.ride(5, new Student("choi"));
bus.ride(10, new Alba("min"));
bus.info();
}
}
반환값
1, kim
2, 비어 있음
3, 비어 있음
4, 비어 있음
5, choi
6, 비어 있음
7, 비어 있음
8, 비어 있음
9, 비어 있음
10, min
11, 비어 있음
12, 비어 있음
13, 비어 있음
14, 비어 있음
15, 비어 있음
16, 비어 있음
17, 비어 있음
18, 비어 있음
19, 비어 있음
20, 비어 있음
21, 비어 있음
22, 비어 있음
23, 비어 있음
24, 비어 있음
25, 비어 있음
장보기
모든 Product은 이름(name)과 가격(price)만 가진다.
package quiz04_cart;
public class Product {
private String name;
private int price;
public Product(String name, int price) {
super();
this.name = name;
this.price = price;
}
// 영수증 만들 때 이름(name)과 가격(price)이 필요하다
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;
}
}
스낵(Snack), 고기(Meat), 우유(Milk는)는 모두 Product이다.
package quiz04_cart;
public class Snack extends Product {
public Snack(String name, int price) {
super(name, price);
}
}
package quiz04_cart;
public class Meat extends Product {
public Meat(String name, int price) {
super(name, price);
}
}
package quiz04_cart;
public class Milk extends Product {
public Milk(String name, int price) {
super(name, price);
}
}
고객(Customer)은 모든 Product을 10개 담을 수 있는 cart를 가진다.
고객은 돈(money)과 보너스포인트(bonusPoint, 구매액의 10%)를 가진다.
package quiz04_cart;
public class Customer {
// 필드
private int money;
private int bonusPoint;
private int total;
private Product[] cart = new Product[10];
private int idx; // cart에 담긴 Product의 개수. cart 배열의 인덱스.
// 생성자 생략
// new Customer() 가능
// 메소드
public int getMoney() {
return money;
}
public void setMoney(int money) { // 실제로는 setMoney만 사용
this.money = money;
}
public int getBonusPoint() {
return bonusPoint;
}
public void setBonusPoint(int bonusPoint) {
this.bonusPoint = bonusPoint;
}
// buy() 메소드
public void buy(Product product) { // UpCasting 사용
int price = product.getPrice();
// 가진 돈보다 비싼 물건은 못 산다.
if(money < price) {
System.out.println(product.getName() + " 사려면 돈이 " + (price - money) + "원 부족합니다.");
return;
}
// 카트가 가득 차면 물건을 못 산다.
if(idx == cart.length) {
System.out.println("카트가 가득 찼습니다.");
return;
}
// 구매
cart[idx++] = product;
money -= price;
total += price;
bonusPoint += price * 0.1;
}
// receipt() 메소드
public void receipt() {
System.out.println();
System.out.println("======== 영수증 ========");
// 물건을 안 샀다.
if(idx == 0) {
System.out.println("구매한 물건이 없습니다.");
return;
}
// 구매 총액 구하기 및 출력
for(int i = 0; i < idx; i++) {
Product product = cart[i];
System.out.println(product.getName() + " " + product.getPrice() + "원");
}
System.out.println("-----------------------");
System.out.println("구매총액 " + total + "원");
System.out.println("보너스 " + bonusPoint + "원");
System.out.println("남은돈 " + money + "원");
}
}
package quiz04_cart;
public class Main {
public static void main(String[] args) {
Customer customer = new Customer(); // 아직 돈이 없는 고객
customer.setMoney(10000); // 10000원이 생긴 고객
customer.buy(new Snack("홈런볼", 1500)); // 1500원 홈런볼을 산다. (카트 담기)
customer.buy(new Meat("한우", 5000)); // 5000원 한우를 산다. (카트 담기)
customer.buy(new Milk("서울우유", 2500)); // 2500원 서울우유를 산다. (카트 담기)
customer.buy(new Meat("불고기", 5000)); // 구매 불가
customer.receipt(); // 영수증을 본다.
}
}
반환값
돈이 4000원 부족합니다.
홈런볼 : 1500원
한우 : 5000원
서울우유 : 2500원
-----------------------
구매총액 : 9000원
보너스 : 900원
거스름돈 : 1000원
package ex01_downcasting;
public class Person {
public void eat() {
System.out.println("먹는다");
}
}
package ex01_downcasting;
public class Student extends Person {
public void study() {
System.out.println("공부한다");
}
}
package ex01_downcasting;
public class Alba extends Student {
public void work() {
System.out.println("일한다");
}
}
instanceof 연산자
- 특정 인스턴스가 어떤 클래스 타입인지 점검하는 연산자
- 해당 클래스 타입이면 true 반환, 아니면 false 반환
package ex01_downcasting;
public class Main {
public static void main(String[] args) {
// 클래스 타입 : Person
// 객체(인스턴스) : p
Person p = new Alba(); // 업캐스팅
// instanceof 연산자
System.out.println(p instanceof Person);
System.out.println(p instanceof Student);
System.out.println(p instanceof Alba);
// p가 Student타입의 인스턴스이면 study() 메소드를 호출할 수 있다.
if(p instanceof Student) {
((Student) p).study(); // 다운캐스팅 p.study() 자동 완성으로 작성
}
// p가 Alba타입의 인스턴스이면 work() 메소드를 호출할 수 있다.
if(p instanceof Alba) {
((Alba) p).work(); // 다운캐스팅 p.work() 자동 완성으로 작성
}
}
}
반환값
true
true
true
공부한다
일한다
임의의 자동차 10대 배열에 저장하기 (33% 확률로 램덤 생성)
package ex02_downcasting;
public class Car {
public void drive() {
System.out.println("운전하다");
}
}
package ex02_downcasting;
public class Ev extends Car {
public void charge() {
System.out.println("충전하다");
}
}
package ex02_downcasting;
public class Hybrid extends Ev {
public void addOil() {
System.out.println("기름을넣는다");
}
}
package ex02_downcasting;
public class Main {
public static void main(String[] args) {
Car[] cars = new Car[10];
for(int i = 0; i < cars.length; i ++) {
if(Math.random() < 0.33) {
cars[i] = new Car();
} else if(Math.random() < 0.66) {
cars[i] = new Ev();
} else {
cars[i] = new Hybrid();
}
}
Car 이면 drive() 호출
Ev 이면 charge() 호출
Hybrid 이면 addOil() 호출
하위클래스인 Hybrid부터 먼저 체크해야 실행된다.
for(int i = 0; i < cars.length; i++) {
if(cars[i] instanceof Hybrid) {
((Hybrid)cars[i]).addOil();
} else if (cars[i] instanceof Ev) {
((Ev)cars[i]).charge();
} else if(cars[i] instanceof Car) {
cars[i].drive();
}
}
}
}
반환값
충전하다
기름을넣는다
충전하다
충전하다
기름을넣는다
운전하다
운전하다
기름을넣는다
운전하다
기름을넣는다