객체 지향의 특성
1. 캡슐화(정보 은닉)
필드 + 메소드 = class
2. 상속
- 부모로부터 어떤 [성질]을 물려받는 것.
- 기존의 클래스(부모 클래스)를 재사용해서 새로운 클래스 작성하는 방법.
- 기존 클래스의 멤버 + 새로운 멤버 = 새 클래스
- 기존 클래스를 부모, 조상 클래스 / 새 클래스를 자식, 자손 클래스라고 함
- 부모 클래스(super class)의 모든 멤버는 자손 클래스에 포함된다.
상속이 안되는 멤버 : 생성자
class Point{
int x, y;
}
class Point3D extends Point{//Point클래스를 확장하여 Point3d를 생성한다 -> 확장하여 생성한 클래스이기 때문에 Point3D로 인스턴스 생성 시 int x, y, z 모두 만들어짐.(생성자는 가져올 수 없다)
int z;
}
// 위 두 클래스를 살펴보니까 Point 클래스와 Point3D 클래스의 차이가 int z 밖에 없다. 그렇다면 상속을 활용하여 불필요한 코딩을 줄일 수 있다.
3. 상속의 장점
1. 클래스의 간결화 : 중복된 코드 작성 불필요.
2. 클래스 관리 용이 : 클래스를 계층적으로 분류 및 관리
3. 소프트웨어의 생산성이 향상됨 클래스의 재사용과 확장 용이. -> 새로운 클래스의 작성에 속도 빠름.
좌표찍기 예시1)
위 두 클래스를 살펴보니까 Point 클래스와 Point3D 클래스의 차이가 int z 밖에 없다. 그렇다면 상속을 활용하여 불필요한 코딩을 줄일 수 있다.
위에서 Point3D 클래스가 Point 클래스를 상속 받았기 때문에 Point 클래스에 선언된 x, y 변수까지 사용할 수 있음.
public class PointTest {
public static void main(String[] args) {
Point p1 = new Point();
Point3D p3_1 = new Point3D();
p1.x = 10;
p1.y = 20;
p3_1.x = 30;
p3_1.y = 40;
p3_1.z = 50;
//클래스가 상속만 된 것이기 때문에 전혀 다른 필드의 x, y 가 만들어짐.
}
}
좌표찍기 예시2) ColorPoint 클래스는 Point 클래스를 상속 받았기 때문에 좌표 입력과 컬러 입출력 모두 가능하다.
//상속 예시 2
public class PointTest2 {
public static void main(String[] args) {
Point p1 = new Point();
ColorPoint cp1 = new ColorPoint();
p1.set(1,2);
p1.showPoint();
cp1.set(3, 4);
cp1.setColor("Red");
cp1.showColorPoint();
}
}
class Point{//특정 위치를 저장하는데 사용하는 클래스
private int x;
private int y;
public void set(int x, int y) {//매개변수랑 변수명 같아서 this 사용
this.x = x;
this.y = y;
}
public void showPoint() {
System.out.println("(" + x + "," + y + ")");
}
}
class ColorPoint extends Point{
private String color;//점의 색상
public void setColor(String color) {
this.color = color;
}
public void showColorPoint() {
System.out.println(color);
showPoint();
}
}
4. 상속의 계층화
예시1)
학생, 알바, 연구원, 교수 클래스
학생 - 말하기, 먹기, 걷기, 잠자기, 공부하기
알바 - 말하기, 먹기, 걷기, 잠자기, 공부하기, 일하기
연구원- 말하기, 먹기, 걷기, 잠자기, 연구하기
교수 - 말하기, 먹기, 걷기, 잠자기, 연구하기, 가르치기
이 중에서 공통 기능을 하나의 클래스로 뽑아냄
그 다음 공통 기능끼리 묶어서 상속시킴
class Person{
public void speaking() {}
public void eating() {}
public void walking() {}
public void sleeping() {}
}
class Student extends Person{
public void studying() {}
}
class StudentWorker extends Student{
public void working() {}
}
5. 상속과 포함관계를 모두 사용한 새로운 클래스 작성
1.) 클래스 간의 관계
1. 상속관계 : is a
2. 포함관계 : has a
2.) 자바에서 클래스의 상속은 단일 상속만 지원(다중 상속 불가)
여러 클래스를 통합할 경우 주가 되는 하나의 클래스를
상속받고 나머지 클래스는 포함관계로 활용.
3.) 다중 상속은 불가지만, 다단 상속은 가능
모든 클래스는 하나의 조상을 갖는다! -> Object 클래스(단군..?)
Tvcr은 Tv 클래스와 Vcr 클래스를 합친 클래스이므로 Tv의 기능을 갖고 있고 추가로 Vcr의 기능을 쓰려면 vcr의 기능을 실행시킬 수 있도록 인스턴스를 생성해주어야 함.
class Tv{
private boolean power;
private int channel;
public void poweron() {
power = !power;
}
public void channelUp() {
channel++;
}
public void channelDown() {
channel--;
}
}
class Vcr{
private boolean power;
int counter = 0;
public void poweron() {
power = !power;
}
public void play() {
//재생 시작
}
public void stop() {
//재생 중단
}
////....
}
class Tvcr extends Tv{
Vcr vcr = new Vcr();
int count = vcr.counter;
void play() {
vcr.play();
}
void stop() {
vcr.stop();
}
}
6. 클래스 상속 받는 방법
1. class 클래스명 extends 상속받을_클래스명 { }
2. 클래스 생성창에서 설정 가능
7. 상속 실습 프로젝트 만들어보기
홈마이너스 마트 제품 관리 프로그램.
카테고리 - 생활필수품(생필품), 가전제품, 식품
제품의 공통 요소(필드) - 부모 클래스 작성
1. 제품명
2. 가격
3. 수량
4. 생산국(제조국)
5. 생산일(제조일)
생필품 전용 요소
1. 제조사
2. 용도
3. 재활용 여부
가전제품
1. 제조사
2. 품질 보증 기간
3. 효율 등급
식품
1. 생산지
2. 유통기한
3. 종류(고기, 생선, 채소, 과일)
1. 패키지 생성
2. 메인 클래스 생성 : 역할 없음
package com.homeminus;
public class HomeMain {
public static void main(String[] args) {
//하는일 없음. 컨트롤러 호출만 실행.
}
}
3. 부모 클래스 생성 (getter/setter 메소드 생성)
package com.homeminus.dto;
public class Product {//부모 클래스
private String name;//제품명
private int price;//가격
private int amount;//수량
private String made;//생산국
private String mday;//제조일자
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;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public String getMade() {
return made;
}
public void setMade(String made) {
this.made = made;
}
public String getMday() {
return mday;
}
public void setMday(String mday) {
this.mday = mday;
}
}
4. ElectProduct 클래스 생성 및 Product 클래스 상속 받음
package com.homeminus.dto;
public class ElectProduct extends Product {
private String maker;//제조사
private int guarantee;//보증기간
private int grade;//효율 등급. 1~5
public String getMaker() {
return maker;
}
public void setMaker(String maker) {
this.maker = maker;
}
public int getGuarantee() {
return guarantee;
}
public void setGuarantee(int guarantee) {
this.guarantee = guarantee;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
}
5. FoodProduct 클래스 생성 및 Product 클래스 상속 받음
package com.homeminus.dto;
public class FoodProduct extends Product {
private String origin;//생산직
private boolean recycle;//재활용 여부
private String usage;//용도: 주방, 욕실, 거실, 베란다 등
public String getOrigin() {
return origin;
}
public void setOrigin(String origin) {
this.origin = origin;
}
public boolean isRecycle() {
return recycle;
}
public void setRecycle(boolean recycle) {
this.recycle = recycle;
}
public String getUsage() {
return usage;
}
public void setUsage(String usage) {
this.usage = usage;
}
}
6. LifeProduct 클래스 생성 및 Product 클래스 상속 받음
package com.homeminus.dto;
public class LifeProduct extends Product {
private String maker;//제조사
private boolean recycle;//재활용 여부
private String usage;//용도: 주방, 욕실, 거실, 베란다 등
public String getMaker() {
return maker;
}
public void setMaker(String maker) {
this.maker = maker;
}
public boolean isRecycle() {
return recycle;
}
public void setRecycle(boolean recycle) {
this.recycle = recycle;
}
public String getUsage() {
return usage;
}
public void setUsage(String usage) {
this.usage = usage;
}
}
8. Override (오버라이드) 오버라이딩(Overriding)
부모 클래스의 메소드를 자손 클래스에서 새로 정의하는 것.
반환형, 이름, 매개변수는 동일하지만, 정의된 내용이 다름.
- 부모 클래스의 메소드가 자손 클래스에서 사용하기에 맞지 않을 때 부모 클래스이 메소드를 덮어써서 새로운 메소드로 다시 만드는 작업.
- 자손 클래스의 인스턴스에서는 부모 클래스의 메소드를 없는 것으로
처리. (메소드가 없어지는 것은 아니며, 부모 클래스의 인스턴스에서는 사용 가능함.) - 부모 클래스의 모든 메소드를 재정의하는 것이 아니라 변경이 필요한 메소드만 재정의 함.
예시1) Object 클래스에 toString() 메소드를 오버라이드 해보자~
public class OverrideTest {
public static void main(String[] args) {
TeaInfo coffee = new TeaInfo();
coffee.setName("아메리카노");
coffee.setPrice(3000);
// System.out.println("이름 : " + coffee.getName() + "\n" + "가격 : " + coffee.getPrice());
System.out.println(coffee);
}
}
class TeaInfo{
private String name;
private int 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;
}
@Override//source->override->toString 선택함~!
public String toString() {//객체를 문자열화 시켜주는 메소드
return "이름 : " + name + "\n" + "가격 : " + price;
}
}
예시2) 오버라이드한 후 메소드 이름 같아도 해당 클래스에서 정의된 기능대로 실행됨
public class OverrideTest {
public static void main(String[] args) {
Point01 p1 = new Point01();
p1.x = 1;
p1.y = 2;
System.out.println(p1.getLocation());
Point3D01 p2 = new Point3D01();
p2.x = 5;
p2.y = 6;
p2.z = 7;
System.out.println(p2.getLocation());
//같은 메소드 이름이지만 다른 클래스에서 호출되기 때문에 다른 출력결과가 나옴
}
}
class Point01{
int x, y;
String getLocation() {
return "x" + x + ", y :" + y;
}
}
class Point3D01 extends Point01{
int z;
@Override //이 표시는 부모클래스의 메소드를 재정의했다는 의미
String getLocation() {
return "x: " + x + ", y: " + y + ", z: " + z;
}
}
9. 상속의 접근 제한
- public : 상속과 관계없이 제약업이 접근가능
- default : 상속과 관계없이 같은 패키지의 클래스에서만 접근 가능
- protected : 같은 패키지와 다른 패키지의 상속받은 클래스에서만 접근 가능
- private : 상속과 관계없이 다른 클래스에서 접근 불가
package1에 A 클래스 만들어주고 4가지 접근 제한 비교해보기
package package1;
public class A {
private int pri;
int def; //default
protected int pro;
public int pub;
}
같은 패키지에서 A 클래스 상속 받은 B클래스 : pri - 접근 불가 / def, pro, pub - 접근 가능
package package1;
public class B extends A {
public void set() {
pri = 1;//private 맴버는 자손 클래스에서 접근 불가
def = 2;//같은 패키지여서 접근 가능
pro = 3;//같은 패키지이거나 상속을 받은 경우 접근 가능
pub = 4;//제한 없음
}
}
다른 패키지에서 A 클래스 상속 받은 C클래스 : pri, def - 접근 불가 / pro, pub - 접근 가능
package package2;
import package1.A;
public class C extends A {
public void set() {
pri = 10;//다른 패키지이기도 하고 자손 클래스는 접근 불가
def = 20;//다른 패키지라서 접근 불가
pro = 30;
pub = 40;
}
}
같은 패키지에서 인스턴스로 접근하는 D클래스 : pri - 접근 불가 / def, pro, pub - 접근 가능
package package1;
public class D {
public void set() {//인스턴스로 접근할 경우 접근 제한
A a = new A();
a.pri = 100;//접근 불가
a.def = 200;//같은 패키지라서 접근 가능
a.pro = 300;//같은 패키지라서 접근 가능
a.pub = 400;
}
}
다른 패키지에서 인스턴스로 접근하는 E클래스 : pri, def, pro - 접근 불가 / pub - 접근 가능
package package2;
import package1.A;
public class E {
public void set() {
A a = new A();
a.pri = 1000;//다른 클래스에서는 무조건 접근 불가
a.def = 2000;//다른 패키지라서 접근 불가
a.pro = 3000;//다른 패키지이고 상속받지 못해서 접근 불가 (다른 패키지이면 받드시 상속을 받아야만 접근 가능)
a.pub = 4000;//접근 가능
}
}
'JAVA' 카테고리의 다른 글
JAVA(22) - 예외처리/Exception Handling/try/catch/finally/throw/ throws (0) | 2020.04.07 |
---|---|
JAVA(21) - Super/부모클래스 생성자 생성 방법/생성자들의 실행 순서 (0) | 2020.03.30 |
JAVA(19) - 생성자/기본 생성자/메소드 오버로딩/Method Overloading/ (0) | 2020.03.18 |
JAVA(18) - 콜백함수/(STATIC/인스턴스)메소드에서 호출 (0) | 2020.03.17 |
JAVA(17) - CardTest/카드 클래스 실습 (0) | 2020.03.17 |