⦁ instanceof 연산자
- 참조변수의 형변환 가능여부 확인에 사용. 가능하면 true 반환
- 형변환 전에 반드시 instanceof로 확인해야 함
void doWork(Car c) {
if (c instanceof FireEngine) { // 1. 형변환이 가능한지 확인
fireEngine fe = (FireEngine)c; // 2. 형변환
fe.water();
...
}
}
- 조상 클래스를 대상으로 하면 true가 나오기 때문에 조심해야 한다.
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
- Q & A
Q. 참조변수의 형변환은 왜 하나요?
A. 참조변수(리모콘)을 변경함으로써 사용할 수 있는 멤버의 개수를 조절하기 위해
Q. instanceof연산자는 언제 사용하나요?
A. 참조변수를 형변환하기 전에 형변환 가능여부를 확인할 때
⦁ 매개변수의 다형성
(장점1. 다형적 매개변수 / 장점2. 하나의 배열로 여러 종류의 객체 다루기)
- 참조형 매개변수는 메소드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
ex)
class Product {
int price; // 제품의 가격
int bonusPoint; // 제품구매 시 제공하는 보너스점수
Product(int price) {
this.price = price;
bonusPoint = (int)(price/10.0); // 보너스점수는 제품가격의 10%
}
}
class Tv1 extends Product {
Tv1() {
// 조상클래스의 생성자 Product(int price)를 호출한다.
super(100); // Tv의 가격을 100만원으로 한다.
}
// Object클래스의 toString()을 오버라이딩 한다.
public String toString() {
return "Tv";
}
}
class Computer extends Product {
Computer() {
super(200);
}
public String toString() {
return "Computer";
}
}
class Buyer { // 고객, 물건을 사는 사람
int money = 1000; // 소유금액
int bonusPoint = 0; // 보너스 점수
void buy(Product p) {
if(money < p.price) {
System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
return;
}
money -= p.price;
bonusPoint += p.bonusPoint;
System.out.println(p + "을/를 구입하셨습니다.");
}
}
public class Ex7_8 {
public static void main(String[] args) {
Buyer b = new Buyer();
// Product p = new Tv1();
// b.buy(p);
b.buy(new Tv1()); // 위의 두 줄을 한 줄로 표현
b.buy(new Computer());
System.out.println("현재 남은 돈은 " + b.money + "만원입니다.");
System.out.println("현재 보너스점수는 " + b.bonusPoint + "점입니다.");
}
}
⦁ 여러 종류의 객체를 배열로 다루기
- 조상타입의 배열에 자손들의 객체를 담을 수 있다.
Product p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
-> Product를 상속하는 Tv, Computer, Audio 객체를 담을 수 있다.
ex) cart와 itemList를 추가한 물품구매
class Product2 {
int price; // 제품의 가격
int bonusPoint; // 제품구매시 제공하는 보너스점수
Product2(int price) {
this.price = price;
bonusPoint = (int)(price/10.0);
}
Product2() {} // 기본 생성자
}
class Tv2 extends Product2 {
Tv2() {
super(100);
}
public String toString() {
return "Tv";
}
}
class Computer2 extends Product2 {
Computer2() {
super(200);
}
public String toString() {
return "Computer";
}
}
class Audio2 extends Product2 {
Audio2() {
super(50);
}
public String toString() {
return "Audio";
}
}
class Buyer2 { // 고객, 물건을 사는 사람
int money = 1000; // 소유금액
int bonusPoint = 0; // 보너스점수
Product2[] cart = new Product2[10]; // 구입한 제품을 저장하기 위한 배열
int i = 0; // Product배열에 사용될 카운터
void buy(Product2 p) {
if (money < p.price) {
System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
return;
}
money -= p.price; // 가진 돈에서 구입한 제품의 가격을 뺀다.
bonusPoint += p.bonusPoint; // 제품의 보너스 점수를 추가한다.
cart[i++] = p; // 제품을 Product[] cart에 저장한다.
System.out.println(p + "을/를 구입하셨습니다.");
}
void summary() { // 구매한 물품에 대한 정보를 요약해서 보여준다.
int sum = 0; // 구입한 물품의 가격 합계
String itemList = ""; // 구입한 물품목록
// 반복문을 이용해서 구입한 물품의 총 가격과 목록을 만든다.
for (int i=0; i<cart.length; i++) {
if(cart[i]==null) {
break;
}
sum += cart[i].price;
itemList += cart[i] + ", ";
}
System.out.println("구입하신 물품의 총 금액은 " + sum + "만원입니다.");
System.out.println("구입하신 제품은 " + itemList + "입니다.");
}
}
public class Ex7_9 {
public static void main(String[] args) {
Buyer2 b = new Buyer2();
b.buy(new Tv2());
b.buy(new Computer2());
b.buy(new Audio2());
b.summary();
}
}
⦁ 추상 클래스 (abstract class)
- 미완성 설계도. 미완성 메소드를 갖고 있는 클래스.
(일반클래스가 추상메소드를 갖고 있으면 추상클래스)
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() { /* 내용 생략 */ } // 추상메소드를 구현
}
AudioPlayer ap = new AudioPlayer(); // OK. 인스턴스 생성 가능
Player ap2 = new AudioPlayer(); // OK.
⦁ 추상 메소드(abstract method)
- 미완성 메소드. 구현부(몸통, {})가 없는 메소드
/* 주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명한다. */
abstract 리턴타입 메소드이름();
꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우에 추상메소드 사용.
abstract class Player {
abstract void play(int pos); // 추상메소드
abstract void stop(); // 추상메소드
}
class AudioPlayer extends Player {
void play(int pos) { /* 내용 생략 */ } // 추상메소드를 구현
void stop() { /* 내용 생략 */ } // 추상메소드를 구현
}
abstract class AbstractPlayer extends Player { // 일부만 구현해도 된다.
void play(int pos) { /* 내용 생략 */ } // 추상메소드를 구현
}
- 추상 메소드 호출 가능(호출할 때는 선언부만 필요)
abstract class Player {
boolean pause; // 일시정지 상태를 저장하기 위한 변수
int currentPos; // 현재 Play되고 있는 위치를 저장하기 위한 변수
Player() {
pause = false;
currentPos = 0;
}
abstract void play(int pos); // 추상메소드
abstract void stop(); // 추상메소드
void play() {
play(currentPos); // 추상메소드를 사용할 수 있다. 메소드는 선언부만 알면 호출가능하므로 추상메소드도 호출 가능하다.
}
}
ex)
abstract class Player { // 추상 클래스(미완성 클래스, 미완성 설계도)
abstract void play(int pos); // 추상 메소드(미완성 메소드)
abstract void stop(); // 추상 메소드(선언부만 있고 구현부{}가 없는 메소드
}
// 추상 클래스는 상속을 통해 완성해야 객체 생성가능
class AudioPlayer extends Player {
void play(int pos) {
System.out.println(pos+"위치 부터 play합니다.");
}
void stop() {
System.out.println("재생을 멈춥니다.");
}
}
public class PlayerTest {
public static void main(String[] args) {
// Player p = new Player(); // 추상클래스의 객체를 생성
// AudioPlayer ap = new AudioPlayer();
Player ap = new AudioPlayer(); // 다형성
ap.play(100);
ap.stop();
}
}
⦁ 추상클래스의 작성
- 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존클래스의 공통 부분을 뽑아서 추상클래스를 만든다.
ex)
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) {
/* 지정된 위치로 이동 */
System.out.println("Marine[x=" + x + ", y=" + y + "]");
}
void stimPack() {
/* 스팀팩을 사용한다. */
}
}
class Tank extends Unit { // 탱크
void move(int x, int y) {
/* 지정된 위치로 이동 */
System.out.println("Tank[x=" + x + ", y=" + y + "]");
}
void changeMode() {
/* 공격모드를 변환한다. */
}
}
class Dropship extends Unit { // 수송선
void move(int x, int y) {
/* 지정된 위치로 이동 */
System.out.println("Dropship[x=" + x + ", y=" + y + "]");
}
void load() {
/* 선택된 대상을 태운다. */
}
void unload() {
/* 선택된 대상을 내린다. */
}
}
public class Ex7_10 {
public static void main(String[] args) {
Unit[] group = { new Marine(), new Tank(), new Dropship() };
for(int i=0; i<group.length; i++) {
group[i].move(100, 200);
// group의 타입은 Unit[], group[0], group[1], group[2]의 타입은 Unit이다.
}
}
}
- 추상화 <-> 구체화
추상화된 코드는 구체화된 코드보다 유연하다. 변경에 유리
GregorianCalendar cal = new GregorianCalendar(); // 구체적
Calendar cal = Calendar.getInstance(); // 추상적

⦁ 인터페이스(interface)
- 추상 메소드의 집합
- 구현된 것이 전혀 없는 설계도. 껍데기(모든 멤버가 public)
interface 인터페이스이름 {
public static final 타입 상수이름 = 값; // 변수는 존재할 수 없음
public abstract 메소드이름(매개변수목록); // 추상메소드
}
interface PlayingCard {
public static final int SPADE = 4;
final int DIAMOND = 3; // public static final int DIAMOND = 3;
static int HEART = 2; // public static final int HEART = 2;
int CLOVER = 1; // public static final int CLOVER = 1;
public abstract String getCardNumber();
String getCardKind(); // public abstract String getCardKind();
}
(멤버에 public, abstract, final, static 등등 생략이 가능하다)
- 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상 아님)
- 다중 상속(조상이 여러개)이 가능(추상메소드는 충돌해도 문제 없음)
interface Fightable extends Movable, Attackable { }
interface Movable {
void move(int x, int y);
}
interface Attackable {
void attack(Unit u);
}
⦁ 인터페이스의 구현
- 인터페이스에 정의된 추상 메소드를 완성하는 것
class 클래스이름 implements 인터페이스이름 {
// 인터페이스에 정의된 추상메소드를 모두 구현해야 한다.
}
interface Fightable {
void move(int x, int y); // public abstract가 앞에 생략되어 있음
void attack(Unit u);
}
class Fighter implements Fightable {
public void move(int x, int y) { /* 내용 생략 */ }
public void attack(Unit u) { /* 내용 생략 */ }
}
- 일부만 구현하는 경우, 클래스 앞에 abstract를 붙여야 함.
abstract class Fighter implements Fightable {
public void move(int x, int y) { /* 내용 생략 */ }
// public abstract void attack(Unit u); 가 생략되어 있음
}
⦁ Q & A
Q. 인터페이스란?
A. 추상 메소드의 집합
Q. 인터페이스의 구현이란?
A. 인터페이스의 추상메소드 몸통{} 만들기(미완성 설계도 완성하기)
Q. 추상 클래스와 인터페이스의 공통점은?
A. 추상 메소드를 가지고 있다(미완성 설계도)
Q. 추상 클래스와 인터페이스의 차이점은?
A. 인터페이스는 iv를 가질 수 없다. 생성자, 인스턴스 메소드 다 가질 수 없음.
출처 : 유튜브 남궁성의 정석코딩 [자바의 정석-기초편]
'Java > Java의 정석' 카테고리의 다른 글
220312 Java - Chapter 8. 예외 처리 (0) | 2022.03.13 |
---|---|
220310 Java - Chapter 7. 객체지향개념 II Part.3 (0) | 2022.03.11 |
220308 Java - Chapter 7. 객체지향개념 II Part 1 (0) | 2022.03.09 |
220307 Java - Chapter 6. 객체지향 개념I Part. 2 (0) | 2022.03.07 |
220305 Java - Chapter 6. 객체지향 개념I Part.1 (0) | 2022.03.05 |