- 클래스의 수직 구조 설계
- extends 예약어 사용
- 부모 클래스를 자식 클래스가 상속받으면 부모 클래스의 변수와 메서드가 상속됨
- 부모 클래스의 변수와 메서드를 자신의 것처럼 사용 가능
- 부모클래스는 슈퍼(super), 상위, 베이스 클래스 라고도 부름
- 자식클래스는 서브, 하위, 파생 클래스 라고도 부름
부모클래스
package chapter08;
public class Phone {
String name;
String color;
String company;
void call() {
System.out.println("전화를 건다");
}
void receive() {
System.out.println("전화를 받다");
}
}
자식클래스
package chapter08;
public class SmartPhone extends Phone {
public void installApp() {
System.out.println("앱 설치");
}
}
클래스 사용
package chapter08;
public class SmartPhoneMain {
public static void main(String[] args) {
Phone p = new Phone();
p.name = "전화기";
p.company = "현대";
p.color = "화이트";
System.out.println("Phone 출력");
System.out.println(p.name);
System.out.println(p.company);
System.out.println(p.color);
p.call();
p.receive();
SmartPhone sp = new SmartPhone();
sp.name = "갤럭시";
sp.company = "삼성";
sp.color = "블랙";
System.out.println("SmartPhone 출력");
System.out.println(sp.name);
System.out.println(sp.company);
System.out.println(sp.color);
sp.call();
sp.receive();
sp.installApp();
}
}
super
- 부모 인스턴스 : 자식 클래스에서 super.변수 접근 가능
- super() : 상속 받은 부모의 인스턴스 생성자
- 상속 받은 자식클래스 인스턴스 생성시 부모 클래스가 먼저 만들어 저야 함
- 부모와 자식 클래스 모두 기본생성자 만 있으면 모두 생락 가능
- 부모의 클래스에 오버로딩된 생성자가 있다면 자식 클래스에서 super()로 먼저 호출 해 주어야 함
부모 클래스 기본 생성자
부모클래스
package chapter08;
public class Phone {
// 기본 생성자 생략
public Phone() {
}
}
자식클래스
package chapter08;
public class SmartPhone extends Phone {
// 기본생성자 생략가능
public SmartPhone () {
// super() -> 부모기본생성자 생략가능
super() {
}
}
}
클래스 사용
package chapter08;
public class SmartPhoneMain {
public static void main(String[] args) {
// SmartPhone() -> super() --> 부모인스턴스 생성 --> 자식인스턴스 생성
SmartPhone sp = new SmartPhone();
}
}
부모 클래스 오버로딩 생성자만 있을 때
부모클래스
package chapter08;
public class Phone {
String name;
String color;
String company;
// 오버로딩 생성자
public Phone(String name, String color, String company) {
this.name = name;
this.color = color;
this.company = company;
}
}
자식클래스
- 부모클래스 생성자 super() 생략 불가
package chapter08;
public class SmartPhone extends Phone {
public SmartPhone() {
// 부모 클래스 생성자 호출
super("갤럭시", "블랙", "삼성");
}
}
클래스 사용
package chapter08;
public class SmartPhoneMain {
public static void main(String[] args) {
// SmartPhone() -> super() --> 부모인스턴스 생성 --> 자식인스턴스 생성
SmartPhone p = new SmartPhone();
}
}
메서드 재정의 overriding
- 상속관계에서 부모 클래스의 메서드를 자식 클래스에서 다시 정의 하는 것
- 자식클래스 인스턴스에서는 재정의된 메서드 호출됨
- 다형성에서도 참조된 참조변수에서도 재정의된 자식 메서드 호출됨
부모클래스
package chapter08;
public class Car {
String color;
String name;
public void go() {
System.out.println("전진");
}
void back() {
System.out.println("후진");
}
}
자식클래스
package chapter08;
public class Taxi extends Car {
public void go() {
System.out.println("미터기를 켜고 전진");
}
}
클래스 실행
package chapter08;
public class TaxiMain {
public static void main(String[] args) {
Taxi t = new Taxi();
t.go();
}
}
final
- final 변수 : 변수값 변경불가 - 상수
- final 메서드 : 오버라이딩 불가
- final 클래스 : 상속 불가
final 메서드 : 오버라이딩 불가
class MethodSuper{
final void superMethod(){
System.out.println("super method");
}
}
class MethodChild extends MethodSuper{
void superMethod(){
System.out.println("child method");
}
}
public class FinalMethod{
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
final 클래스 : 상속 불가
public final class FinalClass {
int x;
}
class ChildClass extends FinalClass{
}
다형성 polymorphism
- 하나의 참조(레퍼런스) 변수가 여러 타입의 객체 참조
- 부모 클래스 타입의 참조 변수로 자식 클래스 참조
- 참조된 자식 클래스는 자동으로 부모 클래스 타입으로 변환(UpCasting)
- 다시 자식 클래스가 부모 클래스 참조 시는 명시적으로 캐스팅 해야함(DownCasting)
- 다형성에서도 참조된 참조변수에서도 재정의된 자식 메서드 호출됨
- 부모의 참조변수는 메서드의 인자로 전송등에 활용 됨(매개변수의 다형성)
- 향후 인터페이스에서도 다형성 가능
부모 클래스
package chapter08.poly;
public class Parent {
String name;
void walk() {
System.out.println("부모가 걷는다.");
}
void run() {
System.out.println("부모가 달린다.");
}
}
자식 클래스
package chapter08.poly;
public class Child extends Parent {
String name;
// override
void run() {
System.out.println("자식 달리기");
}
// new
void game() {
System.out.println("자식 게임");
}
}
다형성 확인 - 자동형변환
package chapter08.poly;
public class PolyEx {
public static void main(String[] args) {
Child c = new Child();
c.run();
// 부모클래스의 자료형으로 선언 (자동형변환)
Parent p = new Child();
p.run(); // 재정이된 메서드가 실행
// p.game(); // 에러
}
}
다형성 - 강제형변환
package chapter08.poly;
public class PolyEx2 {
public static void main(String[] args) {
Parent p = new Child();
p.run();
// 자식클래스의 자료형으로 변환 (강제형변환)
Child c = (Child)p;
c.game();
}
}
다형성 활용
부모 클래스
package chapter08;
public class GraphicCard {
public void process() {
System.out.println("그래픽 처리");
}
}
자식 클래스
package chapter08.poly;
public class Amd extends GraphicCard {
public void process() {
System.out.println("AMD 그래픽 처리");
}
}
자식 클래스
package chapter08.poly;
public class Nvidia extends GraphicCard {
public void process() {
System.out.println("Nvidia 그래픽 처리");
}
}
다형성 - 부품 교체 하듯 사용
package chapter08.poly;
public class Computer {
public static void main(String[] args) {
GraphicCard gc = new GraphicCard();
gc.process(); // 원래 그래픽카드 process
gc = new Amd();
gc.process();
gc = new Nvidia();
gc.process();
}
}
다형성 - 매개변수에서 사용
- 부모의 참조 변수로 모든 자식 클래스 처리
package chapter08.poly;
public class Game {
void display(GraphicCard gc) {
gc.process();
}
}
package chapter08.poly;
public class Computer2 {
public static void main(String[] args) {
Game g = new Game();
Amd gc2 = new Amd();
g.display(gc2);
Nvidia gc3 = new Nvidia();
g.display(gc3);
// 다형성으로 처리
GraphicCard gc = new GraphicCard();
g.display(gc);
gc = new Amd();
g.display(gc);
gc = new Nvidia();
g.display(gc);
}
}
클래스간의 관계 - 포함관계(Composite)
- 포함관계 방법으로 클래스 재 사용 가능
- 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것을 뜻 한다
원(Circle)을 나타내는 클래스
class Circle{
int x; // 원점 x 좌표
int y; // 원점 y 좌표
int r; // 반지름
}
포인트(Point) 좌표상의 한점을 나타내는 클래스
class Point{
int x; // x 좌표
int y; // y 좌표
}
포함관계로 Circle 클래스 재작성
class Circle{
Point p = new Point();
int r; // 반지름
}
클래스간의 관계 결정하기
- 상속 관계: is-a 관계 (~은 ~이다)
- 포함 관계: has-a 관계 (~은 ~을 ~가지고 있다)
- 원(Circle)은 점(Point) 이다 : 상속(x)
- 원(Circle)은 점(Point)을 가지고 있다 : 포함(o)
- 스포츠카(SprotsCar)는 차(Car)다 : 상속
포인트 클래스
class Point {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
Point() {
this(0,0);
}
String getXY() {
return "("+x+","+y+")"; // x와 y의 값을 문자열로 반환
}
}
도형 클래스
class Shape {
String color = "black";
void draw() {
System.out.printf("[color=%s]%n", color);
}
}
원 클래스
class Circle extends Shape {
Point center; // 원의 원점좌표
int r; // 반지름
Circle() {
this(new Point(0, 0), 100); // Circle(Point center, int r)를 호출
}
Circle(Point center, int r) {
this.center = center;
this.r = r;
}
void draw() { // 원을 그리는 대신에 원의 정보를 출력하도록 했다.
System.out.printf("[center=(%d, %d), r=%d, color=%s]%n", center.x, center.y, r, color);
}
}
삼각형 클래스
class Triangle extends Shape {
Point[] p = new Point[3];
Triangle(Point[] p) {
this.p = p;
}
void draw() {
System.out.printf("[p1=%s, p2=%s, p3=%s, color=%s]%n", p[0].getXY(), p[1].getXY(), p[2].getXY(), color);
}
}
도형 그리기 테스트
class DrawShape {
public static void main(String[] args) {
Point[] p = { new Point(100, 100),
new Point(140, 50),
new Point(200, 100)
};
Triangle t = new Triangle(p);
Circle c = new Circle(new Point(150, 150), 50);
t.draw(); // 삼각형을 그린다.
c.draw(); // 원을 그린다.
}
}
Object 객체
- 모든 클래스의 부모 클래스
- 모든 클래스 참조 가능
instanceof
- 참조변수가 참조하는 인스턴스 실체 타입 확인
- true 라는 것은 형변환이 가능
package chapter08.poly;
public class ObjectEx {
public static void main(String[] args) {
allObject(new GraphicCard());
allObject(new Amd());
allObject(new Nvidia());
allObject("안녕");
}
public static void allObject(Object obj) {
System.out.println(obj.toString());
if(obj instanceof GraphicCard) {
GraphicCard gc = (GraphicCard)obj;
gc.process();
}
}
}
추상클래스
- 추상화: 클래스간의 공통부분을 뽑아내서 공통의 조상을 만드는 작업
- 추상메서드를 하나 이상 가지고 있는 클래스
- 미완성 메서드를 포함하고 있다는 의미
- 추상클래스의 인스턴스는 생성할 수 없으며 상속을 통해서 자손클래스에 의해서 완성됨
- 추상클래스 자체로는 클래스 역할을 못하지만 새로운 클래스를 작성하는데 있어 바탕이 되는 조상클래스로서의 중요한 의미를 갖음
- 추상클래스도 생성자가 있으며, 멤버변수와 메서드도 가질 수 있음
- 추상메서드를 가지고 있지 않아도 추상클래스로 만들 수 있으며 인스턴스 생성 불가 함
- 추상메서드로 선언하면 자손클래스에서는 반드시 구현해야 한다(구현을 강제 할 수 있다)
추상메서드
- 메서드는 선언부 + 구현부로 구성
- 추상메서드는 선언부만 작성
- abstract return_type method_name(); // {} 넣지 않음
도형클래스 설계
추상클래스
abstract class Shape {
String type;
Shape(String type) {
this.type = type;
}
abstract double area();
abstract double length();
}
추상클래스 상속 받아 구현 1
class Circle extends Shape{
int r;
Circle(int r) {
super("원");
this.r = r;
}
@Override
double area() {
return r * r * Math.PI;
}
@Override
double length() {
return 2 * r * Math.PI;
}
@Override
public String toString() {
return "Shape [type=" + type + ", r=" + r + "]";
}
}
추상클래스 상속 받아 구현 2
class Rectangle extends Shape {
int width, height;
Rectangle(int width, int height) {
super("사각형");
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
@Override
double length() {
return 2 * (width + height);
}
@Override
public String toString() {
return "Shape [type=" + type + ", width=" + width + ", height=" + height+"]";
}
}
테스트
public class ShapeEx {
public static void main(String[] args) {
Shape[] shapes = new Shape[2];
shapes[0] = new Circle(10);
shapes[1] = new Rectangle(5,5);
for(Shape s : shapes) {
System.out.println(s);
System.out.println("넓이:"+s.area()+" 둘레:"+s.length());
}
}
}
클래스 - 배열 Array 사용
부모 클래스 Animal
package chapter08;
public class Animal {
String type;
String name;
Animal(String type, String name) {
this.type = type;
this.name = name;
}
void sleep() {
System.out.println(this.name +"은(는) 잠을 잔다.");
}
}
자식클래스 Eagle
package chapter08;
public class Eagle extends Animal {
Eagle(String type, String name) {
super(type, name);
}
void sleep() {
System.out.println(this.name +"은(는) 하늘에서 잠을 잔다.");
}
}
자식클래스 Tiger
package chapter08;
public class Tiger extends Animal {
Tiger(String type, String name) {
super(type, name);
}
void sleep() {
System.out.println(this.name +"은(는) 산속에서 잠을 잔다.");
}
}
자식클래스 Lion
package chapter08;
public class Lion extends Animal {
Lion(String type, String name) {
super(type, name);
}
void sleep() {
System.out.println(this.name +"은(는) 숲속에서 잠을 잔다.");
}
}
자식클래스 Shark
package chapter08;
public class Shark extends Animal {
Shark(String type, String name) {
super(type, name);
}
void sleep() {
System.out.println(this.name +"은(는) 물속에서 잠을 잔다.");
}
}
테스트
package chapter08;
public class AnimalMain {
public static void main(String[] args) {
Animal[] ani = new Animal[4];
Animal eagle = new Eagle("조류", "독수리");
Animal tiger = new Tiger("포유류", "호랑이");
Animal lion = new Lion("포유류", "사자");
Animal shark = new Shark("어류", "상어");
ani[0] = eagle;
ani[1] = tiger;
ani[2] = lion;
ani[3] = shark;
for (int i=0; i<ani.length; i++) {
ani[i].sleep();
}
System.out.println("=========================");
for(Animal a : ani) {
a.sleep();
}
}
}
클래스 - ArrayList 사용 1
- ArrayList 만 사용시 형변화 필요
- 다양한 자료형의 데이터를 추가 삭제 가능 객체
- 다양한 자료형은 Object 로 입/출력 됨
- 메서드를 통해 입/출력 add(), get()
package chapter08;
import java.util.ArrayList;
public class AnimalMain2 {
public static void main(String[] args) {
ArrayList ani = new ArrayList();
Animal eagle = new Eagle("조류", "독수리");
Animal tiger = new Tiger("포유류", "호랑이");
Animal lion = new Lion("포유류", "사자");
Animal shark = new Shark("어류", "상어");
ani.add(eagle);
ani.add(tiger);
ani.add(lion);
ani.add(shark);
for (int i=0; i<ani.size(); i++) {
Animal a = (Animal)ani.get(i);
a.sleep();
}
System.out.println("=========================");
for(Object o : ani) {
Animal a = (Animal)o;
a.sleep();
}
}
}
클래스 - ArrayList 사용 2
- ArrayList 자료타입 지정 : 자동 형변환
package chapter08;
import java.util.ArrayList;
public class AnimalMain2 {
public static void main(String[] args) {
// <자료타입지정> : 형변화 불필요
ArrayList<Animal> ani = new ArrayList<Animal>();
Animal eagle = new Eagle("조류", "독수리");
Animal tiger = new Tiger("포유류", "호랑이");
Animal lion = new Lion("포유류", "사자");
Animal shark = new Shark("어류", "상어");
ani.add(eagle);
ani.add(tiger);
ani.add(lion);
ani.add(shark);
for (int i=0; i<ani.size(); i++) {
ani.get(i).sleep();;
}
System.out.println("=========================");
for(Animal a : ani) {
a.sleep();
}
}
}
'Java' 카테고리의 다른 글
예외처리 exception (0) | 2022.03.07 |
---|---|
인터페이스 interface (0) | 2022.03.07 |
클래스 class (0) | 2022.03.07 |
배열 array (0) | 2022.03.07 |
함수 - 메서드 function (0) | 2022.03.07 |