티스토리 뷰

day14 190308


오늘은 super키워드와 추상화를 배워봤습니다.

추상클래스, 추상메소드는 유용하게 쓰이니, 자세히 숙지해두시는게 좋을 것 같습니다.


--super

: 부모의 생성자나 메소드를 실행시키는 메소드

* 자식생성자가 만들어지자마자 자식생성자의 안에서 맨 처음 첫줄에서 super();로 부모생성자가 생성된다.

   super(매개변수~);

* 재정의된 메소드를 두고, 부모의 메소드를 사용하려고 할 때 사용.

  super.재정의된 부모메소드;


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Car /* extends Objcect */ {
    // 자식클래스에 상속되지 않음 ( private 접근제한과 생성자는 상속되지 않음 )
    private String name;
    private int speed;
...
    public Car(String name, int speed) {
        this.name = name;
        this.speed = speed;
        System.out.println("Car(String, int)생성자가 실행됨");
    } 
 
...
 
    public void carInfo() {
        System.out.println("### 차량정보 ###");
        System.out.println("모 델 명 : " + name);
        System.out.println("속      도 : " + speed);
    }
}
 
cs

>> 기존Car클래스에 6행의 생성자와, 14행 carInfro메소드를 추가했습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Genesis extends Car {
    private int price;
 
    public Genesis() {
        // super(); //<< 자식생성자의 첫줄에 항상 부모생성자가 생략되어 입력되어 있다.
        System.out.println("Genesis 생성자가 실행됨");
    }
    public Genesis(String name, int speed, int price) {
        super(name, speed);
        this.price= price;
        System.out.println("Genesis(String, int, int)생성자가 실행됨");
    }
 
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
    
    public void carInfo() {
        /*System.out.println("### 차량정보 ###");
        System.out.println("모델명 : " + getName());
        System.out.println("속도 : " + getSpeed());*/
 
        super.carInfo();    // 부모클래스에 정의된 carInfo() 호출
        System.out.println("가      격 : " + price);
    }
}
cs

>> 9행처럼 부모의 생성자를 super키워드를 통해 불러와서 적용시킬 수 있고,

     22~24행처럼 나타낼 것을, 26행으로 부모클래스의 carInfo메소드를 호출시켜 사용할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
public class CarApp2 {
    public static void main(String[] args) {
        Genesis car1 = new Genesis();
        car1.setName("G90");
        car1.setSpeed(350);
        car1.setPrice(100000000);
        car1.carInfo();
        
        Genesis car2 = new Genesis("G90L"400150000000);
        car2.carInfo();
    }
}
cs

>> 위 클래스파일을 실행하면,

---------- 실행 ----------                        << 왼쪽과 같이, 부모클래스의 생성자를 실행시켜

Car 생성자가 실행됨                                   자식클래스의 생성자에 적용되고,

Genesis 생성자가 실행됨

### 차량정보 ###                                    차량정보 출력역시 부모의 메소드를 합쳐서

모 델 명 : G90                                         출력된다는 것을 볼 수 있다.

  도 : 350

  격 : 100000000

Car(String, int)생성자가 실행됨

Genesis(String, int, int)생성자가 실행됨

### 차량정보 ###

모 델 명 : G90L

  도 : 400

  격 : 150000000



<추상화>

: 실질적인 구현 내용이 없는것

목적 : 실체 클래스들의 공통된 메소드 이름을 통일할 목적.


--추상클래스 : 구현부가 없는 추상메소드를 가질 수 있는 클래스.

       *abstract키워드를 붙여서 정의.

       *new키워드를 사용해서 객체생성할 수 없다.

      public abstract class Printer {

...

      }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class Printer {        // 추상클래스 abstract키워드
    // 모든 프린터가 가지고 있는 기능(종류에 상관없이 동일한 기능들)
    // 자식클래스의 구현부담을 줄여준다.
    public void on() {
        System.out.println("전원 켜기");
    }
    public void off() {
        System.out.println("전원 끄기");
    }
    public void feed() {
        System.out.println("용지 공급하기");
    }
 
    // 추상메소드 정의
    // 모든 프린터들이 가지고 있는 출력기능(프린터마다 구현내용이 다를 것으로 예상)
    // void print()라는 추상메소드로 추상화함으로써
    // 모든 프린터들이 출력기능은 void print() { 구현부 }로 통일해서 정의하게 만듦
    public abstract void print();
}
cs

>> 1행과 같이, class앞에 abstract키워드를 사용하여, 추상 클래스를 만든다.

추상클래스에는 추상메소드가 필요하게 되는데, 18행처럼 메소드의 타입형식에 abstract키워드를 붙이고,

추상메소드의 구현부는 비워두는 것을 원칙으로 한다. ( {}도 작성하지 않는다. )


1
2
3
4
5
6
public class BlackAndWhitePrinter extends Printer {        // 부모의 추상메소드를 재정의 하지않으면 컴파일 오류
    // Printer로부터 상속받은 추상메소드를 구현부를 가진 메소드로 만든다.
    public void print() {
        System.out.println("흑백 출력");
    }
}
cs

>> 추상클래스인 Printer를 상속받은 BlackAndWhitePrinter클래스이다.

3~6행 : Printer에 있는 추상메소드인 print를 재정의하여, 사용한다.


--추상메소드 : 구현부가 없는 공통되는 메소드

       추상클래스 안에만 정의할 수 있다.

      (재정의하는 해당 클래스에서 실제 구현)

      << 구현해야할 스펙을 제시해준다.

      public abstract void print() << 구현부가 없다.

      public abstract void print() {}         << 수행문이 없다. (추상메소드 x , 오류발생)

1
2
3
4
5
6
7
8
9
10
public class ColorPrinter extends Printer {
    // Printer 클래스에 정의된 추상메소드 재정의
    public void print() {
        System.out.println("컬러로 출력합니다.");
    }
    // ColorPrinter의 고유기능
    public void photo() {
        System.out.println("고품질 사진을 출력합니다.");
    }
}
cs

 ColorPrinter클래스에 추상메소드를 재정의한 print와, 고유기능인 photo메소드를 만들고 아래 사용을 통해서

어떻게 진행되는지 보겠습니다.


(--구현클래스) : 일반적인 클래스.

        추상메소드를 절대로 가질 수 없다.

        *만약 추상클래스인 부모로부터 추상메소드를 상속받았다면

         반드시 재정의하여 구현부를 가진 메소드로 만들어야한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class PrinterApp {
    public static void main(String[] args) {
        // Printer p1 = new Printer();     Printer는 추상클래스라서 new키워드로 생성불가
        BlackAndWhitePrinter p1 = new BlackAndWhitePrinter();
        // Printer p3 = new BlackAndWhitePrinter();        << 가능
        p1.on();
        p1.feed();
        p1.print();
        p1.off();
 
        ColorPrinter p2 = new ColorPrinter();
        p2.on();
        p2.feed();
        p2.print();
        p2.photo();
        p2.off();
 
        Printer p3 = new ColorPrinter();
        p3.on();
        p3.feed();
        p3.print();
        //p3.photo();        // 컴파일오류
        p3.off();
    }
}
cs

3행을 보면 위에 설명에서 말했듯, 추상클래스는 new키워드로 직접 생성할 수 없고, 자식클래스를 참조변수로 해서는 가능하다.

6행은 부모인 추상클래스를 상속받아 재정의하고 메소드드들을 그대로 사용하였고,

11행은 6행에서 더해, 자신의 고유기능까지 사용하였다. 18행에서와 같이 자식클래스를 참조변수로 생성하면,

22행은 자식클래스의 고유기능이므로 컴파일 오류가 나게된다.

---------- 실행 ----------

전원 켜기

용지 공급하기

흑백 출력

전원 끄기


전원 켜기

용지 공급하기

컬러로 출력합니다.

고품질 사진을 출력합니다.

전원 끄기


전원 켜기

용지 공급하기

컬러로 출력합니다.

전원 끄기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class DatabaseAccess {
    public void connect() {
        System.out.println("데이터베이스와 연결");
    }
    public void command() {
        System.out.println("데이터베이스에 쿼리문 전송");
    }
    public void receive() {
        System.out.println("데이터베이스로부터 데이터 획득");
    }
    public void disconnect() {
        System.out.println("데이터베이스와 연결해제");
    }
    public abstract void display();
    public void access() {
        connect();
        command();
        receive();
        display();
        disconnect();
    }
}
cs

추상클래스 Database, 추상메소드 display와, Database의 메소드들을 실행시키는 메소드 access이다.


1
2
3
4
5
6
7
8
9
10
11
public class 출석부조회 extends DatabaseAccess {
    public void display() {
        System.out.println("조회된 정보를 출석부에 표시합니다.");
    }
}
 
public class 성적조회 extends DatabaseAccess {
    public void display() {
        System.out.println("조회된 정보를 성적표에 표시합니다.");
    }
}
cs
Database를 상속받은 출석부조회, 성적조회 클래스에 각각 추상메소드에 다른 재정의를 한다.

1
2
3
4
5
6
7
8
9
public class DatabaseAccessApp {
    public static void main(String[] args) {
        출석부조회 a = new 출석부조회();
        a.access();
        System.out.println();
        성적조회 b = new 성적조회();
        b.access();
    }
}
cs
출석부조회, 성적조회를 각각 실행시켜보면,
---------- 실행 ----------
데이터베이스와 연결                                왼쪽 결과와 같이 다르게 출력되는 것을 알 수 있다.
데이터베이스에 쿼리문 전송
데이터베이스로부터 데이터 획득
조회된 정보를 출석부에 표시합니다.
데이터베이스와 연결해제

데이터베이스와 연결
데이터베이스에 쿼리문 전송
데이터베이스로부터 데이터 획득
조회된 정보를 성적표에 표시합니다.
데이터베이스와 연결해제



코딩tip!

개발자 권장도서

<클린 코드> : 코딩을 좀더 깨끗하게 할 수 있도록 도와주는 책 ( 한 언어를 어느정도 숙지후 보는 걸 권장)

<헤드퍼스트 디자인 패턴> : 디자인 패턴들에 대해 설명해주는 책 ( 실무 2년차즈음 권장)

<이펙티브 자바> : 자바를 효율적으로 코딩하게 해주는 책 (자바 숙지후 권장)


사자, 호랑이, 토끼 등의 객체에 공통된 동물이라는 특징이 있을 때, 자바에서는 그 특징을 동물이라는 추상클래스라는 것을 통하여 정의합니다. 또, 동물이라는 추상클래스에 마찬가지로 공통된 점인 다리가 있는 것, 털이 있는 것 등을 추상메소드로 정의를 합니다.


여태까지, 배운 것들을 토대로 과제를 만들어보았습니다.

과제> 

카테고리를 입력받고 카테고리생성, 

카테고리별 제품정보를 입력받고 제품생성,

카테고리 출력, 제품출력, 카테고리별 제품 출력.

CategoryProject.zip


아래는 금일 사용한 소스입니다.

day14.zip


댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함