열심히 끝까지
Java1 day07 본문
[7일차 수업 내용]
1. 상속
2. 오버라이딩
====================================================================
1. 상속 ( inheritance )
1-1 ) 상속의 정의와 장점
- 상속이란 기존 클래스를 재사용하여 새로운 클래스를 작성하는 것
- 상속을 통해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고,
코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이
==> 코드의 재사용성을 높이고 코드의 중복을 제거하여
프로그램의 생성성과 유지보수에 크게 기여
- 상속을 구현하기 위해선 새로 작성하고자 하는 클래스의 이름 뒤에 상속받고자 하는
클래스의 이름을 키워드 extends와 함께 써 주기만 하면 됨
Ex) class Child extends Parents{ }
조상클래스 부모(parent)클래스, 상위(super)클래스, 기반(base)
자손클래스 자식(child)클래스, 하위(sub)클래스, 파생된(derived)클래스
- 생성자와 초기화블록은 상속되지 않으며 멤버만 상속
- 자손클래스의 멤버 개수는 조상클래스보다 항상 같거나 많음
- 자손클래스의 인스턴스를 생성하면 조상클래스의 멤버와 자손클래스의 멤버가 합쳐진
하나의 인스턴스가 생성
1-2 ) 클래스간의 관계 - 포함관계
- 상속이외에도 클래스를 재사용하는 또 다른 방법이 있는데
그것은 클래스간에 포함관계를 맺어주는 것
- 클래스간의 포함관계를 맺어 주는 것은 한 클래스의 멤버변수로
다른 클래스 타입의 창조변수를 선언하는 것을 뜻함
class C extends A, B{ } (X)
class C extends A{
B, b;
}
- 클래스를 작성하는 데 있어서 상속관계를 맺어 줄 것인지
포함관계를 맺어줄 것인지 결정하는 것은 때때로 혼란스러움
상속관계 '~은 ~이다(is -a)'
포함관계 '~은 ~을 가지고 있다.(has -a)'
원(Circle), 점(Point)
원(Circle)은 점(Point) ==> Circle is a Point
원(Circle)은 점(Point)을 가지고 있다. ==> Circle has a Point ==> 포함관계
1-3 ) 단일상속
- 다른 객체지향언어인 C++에선 다중상속을 허용하지만
자바에서는 오직 단일상속만을 허용
- 예를 들어 TV 클래스와 VCR클래스가 있을 때
두 클래스로부터 상속을 받는 TVCR클래스를 작성할 수 없음
만약 다중상속이 허용된다고 할 때 두 클래스 모두 power()라는 메소드가 있다면
어느 조상클래스의 power()를 상속받게 되는 것일까?
- 자바에서는 다중상속의 이러한 문제점을 해결하기 위해
다중상속의 장점을 포기하고 단일상속만 허용
==> 이럴 때 포함관계를 사용 가능
1-4 ) Object클래스 - 모든 클래스의 조상
- Object 클래스는 모든 클래스의 상송계층도의 최상위에 있는 조상클래스
- 자바의 모든 클래스들은 Object클래스의 멤버들을 상속받기 때문에
Object클래스에 정의된 멤버들을 사용할 수 있음
============================================================================
2. 오버라이딩 ( overriding )
2-1 ) 오버라이딩이란?
- 조상클래스로부터 상속받은 메소드의 내용을 변경하는 것을
오버라이딩이라고 한다.
- 상속받은 메소드를 그대로 사용하기도 하지만,
자손클래스 자신에 맞게 변경해야 하는 경우가 많음
==> 이럴 때 조상의 메소드를 오버라이딩
2-2 ) 오버라이딩의 조건
- 자손클래스에서 오버라이딩하는 메소드는
조상클래스의 메소드의 이름, 매개변수, 반환타입이 같아야 함(선언부 변경 X)
① 접근제어자는 조상클래스의 메소드보다 좁은 범위로 변경할 수 없음
- 만일 조상클래스의 정의된 메소드의 접근제어자가 protected라면
이를 오버라이딩하는 자손클래스의 메소드는
접근제어자가 protected 또는 public이어야 함
( 대부분 같은 접근 제어자를 사용한다 )
② 조상클래스의 메소드보다 많은 수의 예외를 선언할 수 없음
③ 인스턴스메소드를 static 메소드 또는 그 반대로 변경할 수 없음
2-3 ) 오버로딩 vs 오버라이딩 **
- 오버로딩은 기존에 없는 새로운 메소드를 추가하는 것,
오버라이딩은 조상으로부터 상속받은 메소드의 내용을 변경하는 것
* 오버로딩( overloading ) : 기존에 없는 새로운 메소드를 정의하는 것( new )
* 오버라이딩( overriding ) : 상속받은 메소드의 내용을 변경하는 것( change, modify )
2-4 ) super
- super는 자손클래스에서 조상클래스로부터
상속받은 멤버를 참조하는데 사용되는 참조변수
- 멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이
상속받은 멤버와 자신의 멤버와 이름이 같을 때는 super를 붙여서 구분할 수 있음
- 조상클래스로부터 상속받은 멤버도 클래스 자신의 멤버이므로 super대신 this를 사용할 수 있음
- 그래도 조상클래스의 멤버와 자손클래스의 멤버가 중복정의되어서 서로 구별해야 하는 경우에만
super를 사용하는 것이 좋음
2-5 ) super()
- this()와 마찬가지로 super()역시 생성자이다.
- this()는 같은 클래스의 다른 생성자를 호출하지만
super()는 조상클래스의 생성자를 호출하는데 사용
- 자손클래스의 인스턴스를 생성하면,
자손의 멤버와 조상의 멤버가 합쳐진 하나의 인스턴스가 생성됨
- 이 때 조상클래스의 멤버의 초기화작업이 수행되어야하기 때문에
자손클래스의 생성자에서 조상클래스의 생성자가 호출되어야 함
- 생성자의 첫줄에서 조상클래스의 생성자를 호출하는 이유는
자손클래스의 멤버가 조상클래스의 멤버를 사용할 수도 있으므로
조상의 멤버들이 먼저 초기화 되어있어야 함
============================================================================
package example01;
public class Bicycle {
int id;
String brand;
String owner;
}
--------------------
package example01;
public class MountainBicycle extends Bicycle{
String frame;
int gear;
int price;
String sector;
void info() {
System.out.println("id : " + this.id);
System.out.println("brand : " + this.brand);
System.out.println("owner : " + this.owner);
System.out.println("frame : " + this.frame);
System.out.println("gear : " + this.gear);
System.out.println("price : " + this.price);
System.out.println("sector : " + this.sector);
}
public static void main(String[] args) {
MountainBicycle mb = new MountainBicycle();
mb.id = 1111;
mb.brand = "삼천리";
mb.frame = "알루미늄";
mb.gear = 33;
mb.price = 300000;
mb.owner = "이용현";
mb.sector = "삼천리";
mb.info();
}
}
------------------------------------------------------------------------
package example01;
public class VCR {
boolean power;
int counter = 0;
void power() {
power = !power;
}
void play() {}
void stop() {}
void rew() {}
}
-------------------------------------
package example01;
public class Tv {
boolean power;
int channel;
void power() {
power = !power;
}
void channelUp() {
channel++;
}
void channelDown() {
channel--;
}
}
----------------------------------
package example01;
public class TVCR extends Tv{
VCR vcr = new VCR();
void play() {
vcr.play();
}
void stop() {
vcr.stop();
}
void rew() {
vcr.rew();
}
public static void main(String[] args) {
TVCR tc = new TVCR();
// Tv클래스에서 상속받은 멤버
tc.power();
tc.channelUp();
tc.channelDown();
// VCR의 멤버들을 사용하는 방법
tc.play();
tc.vcr.power();
}
}
----------------------------------------------------------------------------
package example01;
public class InheritanceTest {
public static void main(String[] args) {
Child c = new Child();
c.bye();
c.hello();
c.x = 15;
c.y = 25;
System.out.println("c.x : " + c.x);
System.out.println("c.y : " + c.y);
System.out.println("c.z : " + c.z);
}
}
class Child extends Parent{ // 멤버변수 5개 Parent 3, child 2
int z = 15;
void bye() {
System.out.println("Child의 bye()메소드");
}
}
class Parent{ // 멤버변수 3개
int x = 5;
int y = 10;
void hello() {
System.out.println("Parent의 hello()메소드");
}
}
---------------------------------------------------------------------------------
package example02;
public class Point {
int x;
int y;
// Point(){}
Point(int x , int y){
this.x = x;
this.y = y;
}
String getLocation() {
return "x : " + x + ", y : " + y;
}
}
-----------------------------
package example02;
public class PointTest {
public static void main(String[] args) {
Point3D p3d = new Point3D(1, 2, 3);
System.out.println(p3d.getLocation());
}
}
class Point3D extends Point{
int z;
// Point3D(){ super(); }
public Point3D(int x, int y, int z) {
super(x, y);
// 조상클래스의 매개변수가 있는 생성자를 호출
// 자바에선 기본적으로 부모의 기본생성자(super())를 호출하지만
// 기본생성자가 없을 경우엔 부모클래스에서 기본생성자를 추가하거나
// 자손클래스에 부모클래스의 매개변수가 있는 생성자를 호출해야 한다.
this.z = z;
}
@Override
String getLocation() {
return "x : " + x + ", y : " + y + ", z : " + z;
}
}
-------------------------------------
package example02;
public class SuperTest {
public static void main(String[] args) {
Child c = new Child();
c.method();
System.out.println();
c.method2();
}
}
class Parent{
int x = 10;
int y = 20;
}
class Child extends Parent{
int y = 30;
void method() {
System.out.println("x : " + x); // 10
System.out.println("x : " + this.x); // 10
System.out.println("x : " + super.x); // 10
}
void method2() {
System.out.println("y : " + y); // 30
System.out.println("y : " + this.y); // 30
System.out.println("y : " + super.y); // 20
}
}
------------------------------------------------------------------------------------------
package example03;
public class DrawShape {
public static void main(String[] args) {
Point centerP = new Point(150, 150);
// Circle(point center, int r) 생성자 호출
Circle c = new Circle(centerP, 50);
Circle c1 = new Circle(new Point(100, 100), 40);
c.draw();
c1.draw();
Point[] p = new Point[3];
p[0] = new Point(1,1);
p[1] = new Point(2,2);
p[2] = new Point(3,3);
Point[] p1 = {
new Point(1,1),
new Point(2,2),
new Point(3,3)
};
Triangle t = new Triangle(p);
t.draw();
Triangle t1 = new Triangle(p1);
t1.draw();
}
}
class Shape{
String color = "black";
void draw() {
System.out.println("[color : " + color +"]");
}
}
class Point{
int x, y;
Point(){
this(0, 0);
}
Point(int x, int y){
this.x = x;
this.y = y;
}
String getXY() {
return "(" + x + "," + y + ")"; // Ex. (0,0)
}
}
class Circle extends Shape{
Point center; // 좌표
int r; //반지름
Circle(Point center, int r){
this.center = center;
this.r = r;
}
Circle(){ // Point center = new Point(0,0);
this(new Point(0,0), 100);
}
@Override
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]; // p[0] = 10; p[1] = 2; p[2] = 20;
Triangle(Point[] p) {
this.p = p;
}
@Override
void draw() {
System.out.printf("[p1=%s, p2=%s, p3=%s, color=%s]\n",
p[0].getXY(), p[1].getXY(), p[2].getXY(), color);
}
}
----------------------------------------------------------------------------------------------------------------
package example04;
public class Card {
static final int KIND_MAX = 4; // 카드 무늬의 개수
static final int NUM_MAX = 13; // 무늬별 카드 수
// 무늬를 상수로 지정
static final int CLOVER = 1;
static final int HEART = 2;
static final int DIAMOND = 3;
static final int SPADE = 4;
// 인스턴스 변수 선언
int kind;
int number;
Card(int kind, int number){
this.kind = kind;
this.number = number;
}
@Override
public String toString() {
String kind = ""; // 지역변수
String number = "";
// 무늬설정
switch(this.kind) { // 이 때, this.kind는 위에 int kind를 가리킴
case 1 :
kind = "클로버";
break;
case 2 :
kind = "하트";
break;
case 3 :
kind = "다이아몬드";
break;
case 4 :
kind = "스페이드";
break;
}
// 숫자설정
switch(this.number) {
case 11 :
number = "J";
break;
case 12 :
number = "Q";
break;
case 13 :
number = "K";
break;
default :
number = this.number + "";
}
return "무늬 : " + kind + ", 숫자 : " + number;
}
}
-----------------------------
package example04;
public class Deck {
final int CARD_NUM = 52; // 카드의 개수
Card[] card = new Card[CARD_NUM];
int i = 0;
// 인스턴스 초기화 블록
{
// 52번 반복을 돌면서 카드를 초기화
for(int k = Card.KIND_MAX; k > 0; k--) { // k : 1~4
for(int n = 1; n < Card.NUM_MAX; n++) { // n : 1~13
card[i++] = new Card(k, n);
}
}
}
Deck() {}
// 단순히 섞는 메소드
public void shuffle() {
for(int n = 0; n < 1000; n++) {
int i = (int)(Math.random() * CARD_NUM); // 0 ~ 51
Card tmp = card[0];
card[0] = card[1];
card[1] = tmp; // 교환법칙
}
}
// Deck에서 카드 하나를 임의로 선택
public Card pick() {
int index = (int)(Math.random() * CARD_NUM); // 0 ~ 51
return pick(index);
}
// 지정된 위치(index)에 있는 카드 하나를 선택
public Card pick(int index) {
if(0 <= index && index < CARD_NUM) {
return card[index];
}else {
return pick();
}
}
}
-----------------------------
package example04;
public class DeckEx {
public static void main(String[] args) {
Deck d = new Deck();
Card c = d.pick(51);
System.out.println("[카드 섞기 전에 제일 밑에 있는 카드]");
System.out.println(c.toString());
d.shuffle();
System.out.println();
c = d.pick(51);
System.out.println("[카드 섞은 후에 제일 밑에 있는 카드]");
System.out.println(c.toString());
System.out.println();
c = d.pick(200);
System.out.println(c.toString());
System.out.println();
c = d.pick();
System.out.println(c.toString());
}
}
'Java1(주말)' 카테고리의 다른 글
Java1 day08 (0) | 2022.05.01 |
---|---|
Java1 day06 (0) | 2022.04.24 |
Java1 day05 보충 (0) | 2022.04.24 |
Java1 day05 (0) | 2022.04.23 |
Java1 day04 보충 (0) | 2022.04.23 |