내부 클래스 (Inner Class)
내부 클래스란?
- 클래스 안에 선언된 클래스
- 특정 클래스 내에서만 주로 사용되는 클래스를 내부 클래스로 선언한다.
- GUI어플리케이션(AWT, Swing)의 이벤트처리에 주로 사용된다.
내부 클래스의 장점
- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
- 코드의 복잡성을 줄일 수 있다.(캡슐화)
내부 클래스의 종류와 특징
- 내부 클래스의 종류는 변수의 선언위치에 따른 종류와 동일하다.
- 유효범위와 성질도 변수와 유사하므로 비교해보면 이해하기 쉽다.
내부 클래스 ( Inner Class ) | 특 징 ( Chacteristic ) |
인스턴스 클래스 ( Instance class ) | 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 instance멤버처럼 다루어진다. 주로 외부 클래스의 instance멤버들과 관련된 작업에 사용될 목적으로 선언된다. |
스테틱 클래스 ( Static class ) | 외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 sttatic멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static메서드에서 사용될 목적으로 선언된다 |
지역 클래스 ( Local class ) | 외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다. |
익명 클래스 ( Anonymous class ) | 클래스의 선언과 객체의 생성을 동시에 하는 이름 없는 클래스 (일회용) |
Inner Class
중첩(내부) 클래스 (Inner Class)
- 클래스 내부에 또 다른 클래스를 가짐으로 클래스 관리의 효율을 높인 것(static 포함불가)
중첩 클래스의 형식과 생성파일
- 형식) class Outer { class Inner { ... } }
- 생성파일) Outer.class, Outer$Inner.class
중첩 클래스 객체 생성
- Outer.Inner oi = new Outer().new Inner();
Ex
class 실행
package ch07;
public class Outer {
private int height;
private int width;
public Outer(int height, int width) {
this.height = height; this.width = width;
}
public Inner getInner() {
return new Inner();
}
class Inner{ // Outer$Inner.class // 컴파일시 이렇게 separate file로 저장된다
private float rate = 0.5f;
public float capacity() {
return rate * height * width;
}
}
}
실행
package ch07;
public class OuterEx {
public static void main(String[] args) {
Outer out = new Outer(100, 200);
// Inner inner = new Inner(); // 이렇게 하면 이너 클래스를 못 찾고 에러남
Outer.Inner inner1 = out.new Inner();
Outer.Inner inner2 = out.new Inner();
System.out.println(inner1.capacity());
System.out.println(inner2.capacity());
}
}
result :
10000.0
10000.0
GUI ( Graphic User Interface ) 화면에서 주로 사용
내부 클래스의 제어자와 접근성
- 내부 클래스의 접근제어자는 변수에 사용할 수 있는 접근제어자와 동일하다
- static클래스만 static멤버를 정의할 수 있다.
클래스간의 관계
포함관계(composite)
- 한 클래스의 멤버변수로 다른 클래스를 선언하는 것
- 작은 단위의 클래스를 먼저 만들고, 이 들을 조합해서 하나의 커다란 클래스를 만든다.
클래스간의 관계 설정하기 - 상속 vs 중첩
- 가능한 한 많은 관계를 맺어주어 재사용성을 높이고 관리하기 쉽게 한다.
- ‘is-a’와 ‘has-a’를 가지고 문장을 만들어 본다.
Ex - 포함관계
package ch07;
public class Engine {
private int displacement;
private String type;
Engine() {}
Engine (int displacement, String type) {
this.displacement = displacement; this.type = type;
}
void print() {
System.out.println("====================");
System.out.println("displacement : "+displacement);
System.out.println("type : "+type);
}
}
package ch07;
public class Car2 {
private Engine eg; // 포함 : 다른 클래스(객체)를 멤버변수로 사용
private String color;
Car2() {}
Car2(Engine eg, String color) {
this.eg = eg; this.color = color;
}
void print() {
eg.print();
System.out.println("color : "+color);
}
}
package ch07;
public class Car2Ex {
public static void main(String[] args) {
Engine eg1 = new Engine(2000, "GDI");
Engine eg2 = new Engine(1500, "DOHC");
Car2 c1 = new Car2(eg1, "red");
Car2 c2 = new Car2(eg1, "green");
Car2 c3 = new Car2(eg2, "blue");
c1.print(); c2.print(); c3.print();
}
}
result :
====================
displacement : 2000
type : GDI
color : red
====================
displacement : 2000
type : GDI
color : green
====================
displacement : 1500
type : DOHC
color : blue
위의 코드 보완
package ch07;
public class Car2Ex {
public static void main(String[] args) {
Engine eg1 = new Engine(2000, "GDI");
Engine eg2 = new Engine(1500, "DOHC");
Car2 c1 = new Car2(eg1, "red");
Car2 c2 = new Car2(eg1, "green");
Car2 c3 = new Car2(eg2, "blue");
c1.print(); c2.print(); c3.print();
System.out.println("- - - - - - - - - - - - - - - -");
Car2[] car = {c1, c2, c3};
for (int i=0; i<car.length;i++) {
car[i].print();
}
System.out.println("- - - - - - - - - - - - - - - -");
Car2[] cars = {c1, c2, c3};
for (Car2 c:car) {
c.print();
}
}
}
result :
====================
displacement : 2000
type : GDI
color : red
====================
displacement : 2000
type : GDI
color : green
====================
displacement : 1500
type : DOHC
color : blue
- - - - - - - - - - - - - - - -
====================
displacement : 2000
type : GDI
color : red
====================
displacement : 2000
type : GDI
color : green
====================
displacement : 1500
type : DOHC
color : blue
- - - - - - - - - - - - - - - -
====================
displacement : 2000
type : GDI
color : red
====================
displacement : 2000
type : GDI
color : green
====================
displacement : 1500
type : DOHC
color : blue
Ex - Apple Sale
seller
package ch07;
public class FruitSeller {
int numberOfApple = 20;
int money = 0;
final int PRICE_PER_APPLE = 1000;
int saleApple(int amt) {
money += amt;
int num = amt/PRICE_PER_APPLE;
numberOfApple -= num;
return num;
}
void print() {
System.out.println("seller apple : "+numberOfApple);
System.out.println("seller money : "+numberOfApple);
}
}
buyer
package ch07;
public class FruitBuyer {
int numberOfApple = 0;
int money = 5000;
void buyFruit (FruitSeller fs, int amt) {
int num = fs.saleApple(amt);
money-=amt;
numberOfApple+=num;
}
void print() {
System.out.println("buyer apple : "+numberOfApple);
System.out.println("buyer money : "+money);
System.out.println("=====================");
}
ex
package ch07;
public class FruitEx {
public static void main(String[] args) {
FruitSeller fs1 = new FruitSeller();
FruitSeller fs2 = new FruitSeller();
FruitBuyer fb1 = new FruitBuyer();
FruitBuyer fb2 = new FruitBuyer();
FruitBuyer fb2 = new FruitBuyer();
fb1.buyFruit(fs1, 3000);
fb1.buyFruit(fs2, 2000);
fb2.buyFruit(fs1, 2000);
fs1.print(); fs2.print();
fb1.print(); fb2.print();
}
}
result
seller apple : 15
seller money : 15
seller apple : 18
seller money : 18
buyer apple : 5
buyer money : 0
=====================
buyer apple : 2
buyer money : 3000
=====================
Ex - Apple Sale 3
seller
package ch07;
public class FruitSeller3 {
String name; int numberOfApple, money;
final int PRICE_PER_APPLE = 1000;
public FruitSeller3(String name, int numberOfApple, int money) {
this.name = name; this.numberOfApple=numberOfApple; this.money = money;
}
int saleApple(int amt) {
int num = amt/PRICE_PER_APPLE;
if (numberOfApple>=num) {
money += amt;
numberOfApple -= num;
System.out.printf("%s sold %d apple for %d won\n",name , num, amt);
} else {
System.out.println(name+" : sold out");
num=0;
}
return num;
}
void print() {
System.out.println(name+" apple : "+numberOfApple);
System.out.println(name+" money : "+money);
System.out.println("---------------------------");
}
}
buyer
package ch07;
public class FruitBuyer3 {
String name; int numberOfApple=0, money=5000;
public FruitBuyer3(String name, int money, int numberOfApple) {
this.name = name; this.money = money; this.numberOfApple=numberOfApple;
}
void buyFruit(FruitSeller3 fs, int amt) {
if (money<amt) {
System.out.println(name+" : not enough money");
}
else {
int num = fs.saleApple(amt);
if (num !=0) {
money -= amt;
numberOfApple += num;
System.out.printf("%s bought %d apple for %d won\n", name, num, amt);
} else System.out.println(name+" : sold out? i'm disappointed");
}
}
void print() {
System.out.println(name+" apple : "+numberOfApple);
System.out.println(name+" money : "+money);
System.out.println("---------------------------");
}
}
ex
package ch07;
public class FruitEx3 {
public static void main(String[] args) {
FruitSeller3 fs1 = new FruitSeller3("Cindy", 30, 1000);
FruitSeller3 fs2 = new FruitSeller3("Teddy", 5, 0);
FruitBuyer3 fb1 = new FruitBuyer3("Larry", 20000, 0);
FruitBuyer3 fb2 = new FruitBuyer3("Penelope", 10000, 5);
fb1.buyFruit(fs1, 3000);
fb1.buyFruit(fs2, 2000);
fb2.buyFruit(fs1, 12000);
fb2.buyFruit(fs2, 5000);
fs1.print(); fs2.print();
fb1.print(); fb2.print();
}
}
result :
Cindy sold 3 apple for 3000 won
Larry bought 3 apple for 3000 won
Teddy sold 2 apple for 2000 won
Larry bought 2 apple for 2000 won
Penelope : not enough money
Teddy : sold out
Penelope : sold out? i'm disappointed
Cindy apple : 27
Cindy money : 4000
---------------------------
Teddy apple : 3
Teddy money : 2000
---------------------------
Larry apple : 5
Larry money : 15000
---------------------------
Penelope apple : 5
Penelope money : 10000
---------------------------
참조변수의 형변환
참조변수의 형변환
- 서로 상속관계에 있는 타입간의 형변환만 가능하다.
- 자손 타입에서 조샅타입으로 형변환하는 경우, 형변환 생략가능
자손타입 --> 조상타입 (Up-casting) : 형변환 생략 가능
자손타입 <-- 조상타입 (Down-casting) : 형변호나 생략 불가
instanceof 연산자
- 참조변수가 참조하는 인스턴스의 실제 타입을 체크하는데 사용.
- 이항연산자이며 피연산자는 참조형 변수와 타입. 연산결과는 true, false.
- instanceof의 연산결과가 true이면, 해당 타입으로 형변환이 가능하다.
public class Car2Ex2 {
public static void main(String[] args) {
FireEngine fe = new FireEngine(); Ambulance ab = new Ambulance(); Car2[] car = new Car2[2];
car[0] = fe; car[1] = ab;
for (Car2 c : car) {
c.drive(); // 부모에 있는 메소드만 실행 가능
// 실행되는 메소드는 자식 것
// c.job();
if (c instanceof FireEngine) {
FireEngine fe2 = (FireEngine)c;
fe2.job();
}
}
}
참조변수와 인스턴스변수의 연결
- 멤버변수가 중복정의된 경우, 참조변수의 타입에 따라 연결되는 멤버변수가 달라진다. (참조변수타입에 영향받음)
- 메서드가 중복정의된 경우, 참조변수의 타입에 관계없이 항상 실제 인스턴스의 타입에 정의된 메서드가 호출된다.(참조변수타입에 영향받지 않음)
Ex
package ch07;
public class Car3 {
String color = "blue";
void drive() {
System.out.println("Lego!");
}
}
class FireEngine3 extends Car3{
String color = "red";
void drive() {
System.out.println("with lots of water");
}
void fire() {
System.out.println("On way to fight the fire");
}
}
class Ambulance3 extends Car3 {
String color= "white";
void drive() {
System.out.println("got a patient");
}
}
class Bus3 extends Car3 {
void drive() {
System.out.println("up to 45 people");
}
}
>>
package ch07;
public class Car3Ex {
public static void main(String[] args) {
// 부모를 선언하고 자식을 생성; 범위가 작은 곳에서 넓은 곳 up casting 묵시적
Car3 car1 = new FireEngine3();
Car3 car2 = new Ambulance3();
Car3 car3 = new Bus3();
// 부모를 선언하고 자식을 생성하여 대입하면 부모가 가지고 있는 메서드와 멤버변수만 사용 가능
// 실제로 실행되는 내용은 자식 메서드
car1.drive(); car2.drive(); car3.drive(); // car1.fire();
System.out.println("====================");
Car3[] cars = {car1, car2, car3};
for (Car3 car:cars) {
System.out.println(car.color); // 변수는 부모의 값이 실행
car.drive(); // 메서드는 자식 메서드 실행
}
}
}
result :
with lots of water
got a patient
up to 45 people
====================
blue
with lots of water
blue
got a patient
blue
up to 45 people
>>> 변수는 부모의 값이 실행
>>> 메서드는 자식 메서드 실행
package ch07;
public class Car3Ex {
public static void main(String[] args) {
// 부모를 선언하고 자식을 생성; 범위가 작은 곳에서 넓은 곳 up casting 묵시적
Car3 car1 = new FireEngine3();
Car3 car2 = new Ambulance3();
Car3 car3 = new Bus3();
// 부모를 선언하고 자식을 생성하여 대입하면 부모가 가지고 있는 메서드와 멤버변수만 사용 가능
// 실제로 실행되는 내용은 자식 메서드
car1.drive(); car2.drive(); car3.drive(); // car1.fire();
System.out.println("====================");
Car3[] cars = {car1, car2, car3};
for (Car3 car:cars) {
// 변수는 부모의 값이 실행, 변수는 이름은 같지만 다른 변수로 인식
System.out.println(car.color); // 변수는 부모의 값이 실행
car.drive(); // 메서드는 자식 메서드 실행
// 원래 FireEngine3였던 car는 에러가 발생하지 않지만 다른 경우에는 에러 발생
FireEngine3 fEngine3 = (FireEngine3)car;
fe.fire();
}
}
}
> 아래 두 줄 에러 발생
package ch07;
public class Car3Ex {
public static void main(String[] args) {
// 부모를 선언하고 자식을 생성; 범위가 작은 곳에서 넓은 곳 up casting 묵시적
Car3 car1 = new FireEngine3();
Car3 car2 = new Ambulance3();
Car3 car3 = new Bus3();
// 부모를 선언하고 자식을 생성하여 대입하면 부모가 가지고 있는 메서드와 멤버변수만 사용 가능
// 실제로 실행되는 내용은 자식 메서드
car1.drive(); car2.drive(); car3.drive(); // car1.fire();
System.out.println("====================");
Car3[] cars = {car1, car2, car3};
for (Car3 car:cars) {
// 변수는 부모의 값이 실행, 변수는 이름은 같지만 다른 변수로 인식
System.out.println(car.color); // 변수는 부모의 값이 실행
car.drive(); // 메서드는 자식 메서드 실행
// 원래 FireEngine3였던 car는 에러가 발생하지 않지만 다른 경우에는 에러 발생
// FireEngine3 fEngine3 = (FireEngine3)car;
// fe.fire();
if (car instanceof FireEngine3) // 현재 car가 FireEngine3에서 온 것인지 확인
((FireEngine3)car).fire(); // 두 줄을 한 줄로 간편하게 변경
}
}
}
result :
with lots of water
got a patient
up to 45 people
====================
blue
with lots of water
On way to fight the fire
blue
got a patient
blue
up to 45 people
Ex
package ch07;
public class Animal {
int x = 7;
void move() {
System.out.println("move");
}
}
class Pig extends Animal {
int x = 10;
void move() {
System.out.println("walk with 4 legs");
}
}
class Bird extends Animal {
void move() {
System.out.println("fly with 2 wings");
}
void eat() {
System.out.println("peck peck");
}
}
class Fish extends Animal {
void move() {
System.out.println("swim with 2 fins");
}
}
package ch07;
public class AnimalEx {
public static void main(String[] args) {
Animal[] animals = {new Pig(), new Bird(), new Fish()};
for (Animal a:animals) {
a.move();
System.out.println("x = "+a.x);
if (a instanceof Bird)
((Bird)a).eat();
}
}
}
result :
walk with 4 legs
x = 7
fly with 2 wings
x = 7
peck peck
swim with 2 fins
x = 7
Ex
parent - Person2
package ch07;
public class Person2 {
private String name;
private int age;
public Person2(String name, int age) {
this.name = name; this.age = age;
}
void print() {
System.out.println("==========================");
System.out.println("Name : "+name);
System.out.println("Age : "+age);
}
}
childeren
package ch07;
public class Student2 extends Person2 {
private String sno;
public Student2(String name, int age, String sno) {
super(name, age);
this.sno=sno;
}
void print() {
super.print();
System.out.println("Student number : "+sno);
}
}
class Teacher2 extends Person2 {
private String subject;
public Teacher2(String name, int age, String subject) {
super(name, age); this.subject = subject;
}
void print() {
super.print();
System.out.println("Subject : "+subject);
}
}
class Manager2 extends Person2 {
private String part;
public Manager2(String name, int age, String part) {
super(name, age); this.part = part;
}
void print() {
super.print();
System.out.println("Part : "+part);
}
}
ex - Person2Ex
package ch07;
public class Person2Ex {
public static void main(String[] args) {
Person2[] person = new Person2[6];
person[0] = new Student2("rose", 26, "970201");
person[1] = new Student2("jayden", 25, "960202");
person[2] = new Teacher2("jennie", 27, "Art");
person[3] = new Student2("derek", 32, "Music");
person[4] = new Student2("Lisa", 34, "Accounting");
person[5] = new Student2("Ben", 30, "Cleaning");
for (Person2 p:person) {
p.print();
}
}
}
result :
==========================
Name : rose
Age : 26
Student number : 970201
==========================
Name : jayden
Age : 25
Student number : 960202
==========================
Name : jennie
Age : 27
Subject : Art
==========================
Name : derek
Age : 32
Student number : Music
==========================
Name : Lisa
Age : 34
Student number : Accounting
==========================
Name : Ben
Age : 30
Student number : Cleaning
'Java Class Notes' 카테고리의 다른 글
javaLang (주요 클래스) (0) | 2023.02.28 |
---|---|
Interface (다형성&추상 메서드) (1) | 2023.02.27 |
Inheritance(상속) (0) | 2023.02.24 |
Access Modifier and Encapsulation (접근제어자와 캡슐화) (0) | 2023.02.23 |
Ex - OOP (0) | 2023.02.23 |