사용할 수 있는 멤버의 갯수를 조절하는 것입니다.
(주소값이나 객체는 그대로 유지)
조상 자손 관계의 참조변수만 서로 형변환이 가능합니다.(중요!!)
예제)
class Car {
String color;
int door;
void drive() {
System.out.println("drive~~~");
}
void stop() {
System.out.println("stop!!!");
}
}
class FireEngine extends Car {
void water() {
System.out.println("water");
}
}
class Ambulance extends Car {
//.....
}
class Ex7_7 {
public static void main(String[] args) {
FireEngine f = new FireEngine();
f.water();
Car c = (Car)f; // OK. 조상인 Car타입으로 형변환 가능(형변환 생략가능)
c.water();// 에러!! Car타입의 참조변수로는 water()를 호출할 수 없다.
FireEngine f2 = (FireEngine)c; // OK. 자손인 FireEngine타입으로 형변환(형변환 생략불가)
f2.water();
Ambulance a = (Ambulance)f; // 에러!! 상속관계가 아닌 클래스 간의 형변환 불가
//컴파일러는 괜찮으나 예외에러가 발생하는 경우
//NullPointer Exception
//문법상 문제가 없으나 실제 인스턴스가 생성이 안되어 예외가 발생
Car c2 = null;
FireEngine f3 = (FireEngine)c2; //exception발생
//ClassCast Exception
//참조변수가 가르키는 실제 객체가 중요하다.
//조상의 인스턴스로 생성된 참조변수가 자손으로 형변환시 발생
Car c3 = new Car();
FireEngine f4 = (FireEngine)c3; //exception발생
f4.water();
}
}
참조변수의 형변환(조상, 자손관계확인) 가능여부 확인에 사용합니다.
가능하면 true를 반환합니다.
예제)
void doWork(Car c) {
if(c instanceof FireEngine) { // 1. 형변환이 가능한지 확인
FireEngine fe = (FireEngine)c; // 2. 형변환
fe.water();
......
FireEngine fe = new FireEngine();
System.out.println(fe instanceof Object); // true
System.out.println(fe instanceof Car); // true
System.out.println(fe instanceof FireEngine); // true
A. 참조변수(리모콘)을 변경함으로써 사용할 수 있는 멤버의 갯수를 조절하기 위해서입니다.
A. 참조변수를 형변환하기 전에 형변환 가능여부를 확인할 때 사용합니다.
참조형 매개변수는 메서드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있습니다.
예제)
class Product {
int price; // 제품가격
int bonusPoint; // 보너스 점수
}
class Tv extends Product {}
class Computer extends Product {}
class Audio extenda Product {}
class Buyer { // 물건사는 사람
int money = 1000; // 소유금액
int bonusPoint = 0; // 보너스 점수
void buy(Product p) { //오버로딩할 필요없이 하나의 함수로 해결가능하다.
money -= p.price;
bonusPoint += p.bonusPoint;
}
}
조상타입의 배열에 자손들의 객체를 담을 수 있습니다.
하나의 타입 배열에 여러타입의 변수를 배열로 담아봅시다.
예제)
Product[] p = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
class Buyer {
int money = 1000;
int bonusPoint = 0;
Product [] cart = new Product[10]; //구입한 물건을 담을 배열
int i = 0;
void buy(Product p) {
if(money < p.price) {
System.out.println("잔액부족");
return;
}
money -= p.price;
bonusPoint += p.bonucPoint;
cart[i++] = p;
}
}
실제사용예)
public class Vector extends AbstractList
implements List, Cloneable, java.io.Serializable {
// 모든 클래스의 최고조상인 Object를 이용해서
//어떤 객체든 담을 수 있는 배열 생성
protected Object elementData[];
.....
}
미완성 설계도.
미완성 메서드를 갖을 수 있는 클래스입니다.
abstract class Player { // 추상클래스(미완성클래스)
abstract void play(int pos); //추상메서드(몸통{}이 없는 미완성 메서드)
abstract void stop(); // 추상메서드
}
//다른 클래스 작성에 도움을 주기 위한 것. 인스턴스 생성 불가
Player p = new Player(); // 에러. 추상 클래스의 인스턴스 생성 불가
//상속을 통해 추상 메서드를 완성해야 인스턴스 생성가능
class AudioPlayer extends Player {
void play(int pos) { // 추상메서드 구현
//생략...
}
void stop() { // 추상메서드 구현
//생략....
}
}
Player ap = new AudioPlayer(); //추상클래스도 형변환이 가능하다!
미완성 메서드. 구현부(몸통, {}가 없는 메서드)
꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우에 사용됩니다.
abstract 리턴타입 메서드이름();
예제)
abstract class Player {
abstract void play(int pos);
abstract void stop();
}
class AudioPlayer extends Player {
void play(int pos) { // 추상메서드 구현
//내용 생략
}
void stop() { // 추상메서드 구현
//내용 생략
}
}
//추상메서드를 일부만 구현할 경우 abstract키워드를 붙여야한다.
abstract class AbstractPlayer extends Player {
void play(int pos) { // 추상메서드 1개만 구현
//내용 생략
}
}
여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존 클래스의 공통 부분을 뽑아서 추상클래스를 만듭니다.
예제)
abstract class Unit { //공통된 부분을 추상클래스로 작성
int x, y; //위치
abstract void move(int x, int y);
void stop() {
//현재위치에서 정지
};
}
class Marine extends Unit {
void move(int x, int y) {
//지정된 위치로 이동
}
void stimPack() {
//스팀팩 사용
}
}
class Tank extends Unit {
void move(int x, int y) {
//지정된 위치로 이동
}
void changeMode() {
//공격모드로 변환한다.
}
}
class Dropship extends Unit {
void move(int x, int y) {
//지정된 위치로 이동
}
void load() {
//선택된 대상을 태운다
}
void unload() {
//선택된 대상을 내린다
}
}
public class Ex7_10 {
public static void main(String[] args) {
Unit[] group = {new Marine(), new Tank(), new Dropship()};
for(Unit u : group) {
u.move(100, 200);
}
}
}