1. 추상 클래스 (abstract class)

- 추상 메소드를 가지고 있는 클래스

- 추상 메소드: 메소드의 선언부(헤드)만 있는 메소드 (= 구현이 되지 않은 클래스)

- ex) void print(int n);

 

- 메소드가 미완성이므로 추상 클래스로는 객체 생성 불가능

- 주로 상속 계층에서 추상적인 개념을 나타내기 위한 용도로 사용

 

- 정의: 앞에 abstract 붙임

public abstract class Animal {
    public abstract void move();
}

public class Lion extends Animal {
    public void move() {
        System.out.println("사자의 move() 메소드");
    }
}

- 추상 클래스를 상속 받으면 추상 메소드를 구현해야 함!!

 

- ex) 도형 클래스

- 각 도형은 위치, 회전 각도, 선 색상, 채우는 색 등의 속성은 모든 도형이 공유

- 기준점을 이동하는 메소드 translate()도 모든 도형에서 동일

-> Shape에서 구체적으로 정의됨

- But) draw() 메소드는 도형마다 그리는 방법이 모두 다르기 때문에 구체적으로 정의될 수 없음

- 메소드의 이름과 매개 변수는 정의될 수 있음 -> 추상 메소드 사용

- draw()의 몸체는 각 자식 클래스에서 정의됨

 

abstract class Shape {
    int x, y;
    public void translate(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    pulic abstract void draw();
}

class Rectangle extends Shape {
    int width, height;
    @Override
    public void draw() { System.out.println("Rectangle draw"); }
}

class Circle extends Shape {
    int radius;
    @Override
    public void draw() { System.out.println("Circle draw"); }
}

public class AbstractTest {
    public static void main(String[] args) {
        // Shape s1 = new Shape();  -> 추상 클래스로 객체 생성 불가능
        Shape s2 = new Circle();    // 업캐스팅
        s2.draw();
    }
}

// Circle draw

 

 

-  추상 메소드로 정의되면 자식 클래스에서 반드시 오버라이드 해야함!

 

2. 하드웨어 인터페이스

- 컴퓨터 하드웨어에서 인터페이스는 서로 다른 장치들이 연결되어 상호 데이터를 주고받는 규격을 의미

- 각자의 클래스를 다른 사람의 클래스와 연결하려면 클래스 간의 상호작용을 기술하는 규격 필요 -> 인터페이스로 정의

 

3. 인터페이스의 용도

- 상속 관계가 아닌, 클래스 간의 유사성을 인코딩하는 데 사용됨 

- ex) 사람과 자동차는 둘 다 달릴 수 있지만, 부모 클래스로 Runner로 정의하고 사람과 차를 Runner의 자식 클래스로 나타내는건 이상함

-> Runnable 인터페이스를 만들고 이 인터페이스를 양쪽 클래스가 구현하도록

 

public interface RemoteControl {
    // 추상 메소드 정의
    public void turnOn();
    public void turnOff();
}

- 인터페이스는 추상 메소드들과 디폴트 메소드들로 이루어짐

- 인터페이스 내에 필드 선언될 수 없음!

- 상수는 정의 가능

 

4. 인터페이스 구현과 사용

class Television implements RemoteControl {
    boolean On;
    public void turnOn() {
        on = true;
        System.out.println("TV ON");
    }
    
    public void turnOff() {
        on = false;
        System.out.println("TV OFF");
    }
}

- 인터페이스는 다른 클래스들에 의해 구현될 수 있음

= 인터페이스에 정의된 추상 메소드의 몸체 정의한다는 의미

 

Television t = new Television();
t.turnOn();
t.turnOff();

 

5. 인터페이스 vs 추상 클래스

- 추상 클래스 사용 권장

    - 관련된 클래스들 사이에서 코드 공유하고 싶은 경우

    - 공통적인 필드나 메소드의 수가 많은 경우

    - public 이외의 접근 지정자를 사용해야 하는 경우

    - 일반 멤버 필드를 선언하기 원하는 경우

 

- 인터페이스 사용 권장

    - 관련 없는 클래스들이 동일한 동작을 구현하기 원할 때 (ex. Comparable, Cloneable)

    - 특정한 자료형의 동작을 지정하고 싶지만, 누가 구현하든지 신경 쓸 필요가 없을 때

    - 다중 상속이 필요할 때

 

6. 인터페이스와 타입

- 인터페이스를 정의하는 것 = 새로운 자료형을 정의하는 것!

// Television 객체이지만 RemoteControl 인터페이스 구현
// -> RemoteControl 타입의 변수로 가리킬 수 있음
RemoteControl obj = new Television();

// obj를 통해서는 RemoteControl 인터페이스에 정의된 메소드만 호출 가능
obj.turnOn();
obj.turnOff();

 

- default 함수 오버라이드 가능

interface RemoteControl {
    ...
    public default void printBrand() { System.out.println("Remote Control 가능 TV"); }
}

class Television implements RemoteControl {
    ...
    @Override
    public void printBrand() { System.out.println("Power JAVA TV"); }
}

public class TestInterface {
    public static void main(String[] args) {
        RemoteControl obj = new Television();
        obj.printBrand();
    }
}

// Power JAVA TV

 

7. 인터페이스 상속

- 인터페이스도 다른 인터페이스 상속받을 수 있음!

 

8. 인터페이스를 이용한 다중 상속

- 다중 상속: 하나의 클래스가 여러 개의 부모 클래스를 갖는 것

 

- 동시에 여러 인터페이스 구현

interface Drivable {
    void drive();
}

interface Flyable {
    void fly();
}

public class FlyingCar1 implements Drivable, Flyable {
    public void drive() { System.out.println("I'm driving"); }
    public void fly() { System.out.println("I'm flying"); }
    
    public static void main(String[] args) {
        FlyingCar1 obj = new FlyingCar1();
        obj.drive();
        obj.fly();
    }
}

// I'm driving
// I'm flying

 

- 하나의 클래스 상속받고 또 하나의 인터페이스 구현

interface Flyable { void fly(); }

class Car {
    int speed;
    void setSpeed(int speed) { this.speed = speed; }
}

public class FlyingCar2 extends Car implements Flyable {
    public void fly() { System.out.println("I'm flying!"); }
    
    public static void main(String[] args) {
        FlyingCar2 obj = new FlyingCar2();
        obj.setSpeed(300);
        obj.fly();
    }
}

// I'm flying!

 

9. 인터페이스에서의 상수 정의

- 인터페이스에서 정의된 변수는 자동적으로 public static final이 되어서 상수가 됨!

 

10. 디폴트 메소드와 정적 메소드

- 디폴트 메소드: 인터페이스 개발자가 메소드의 디폴트 구현을 제공할 수 있는 기능

 

11. 자율 주행 자동차 예시

public interface OperateCar {
    void start();
    void stop();
    void setSpeed(int speed);
    void turn(int degree);
}

public class AutoCar implements OperateCar {
    public void start() { System.out.println("출발"); }
    public void sotp() { System.out.println("정지"); }
    pubilc void setSpeed(int speed) { System.out.println("속도를 "+ speed + "km/h로 변경"); }
    public void turn(int degree) { System.out.println("방향을 " + degree + "도 만큼 변경"); }
}

public class AutoCarTest {
    public static void main(String[] args) {
        OperateCar obj = new AutoCar();
        obj.start();
        obj.setSpeed(30);
        obj.turn(15);
        obj.stop();
    }
}

 

12. Comparable 인터페이스

- 객체와 객체의 순서 비교할 때 사용

public interface Comparable {       // 실제로는 제네릭을 사용해서 정의됨
    int compareTo(Object other);    // -1, 0, 1 반환
}

class Rectangle implements Comparable {
    public int width = 0;
    public int height = 0;
    
    @Override
    public String toString() {
        return "Rectangle [width=" + width + ", height=" + height + "]";
    }
    
    public Rectangle(int w, int h) {
        width = w;
        height = h;
        System.out.println(this);
    }
    
    public int getArea() {
        return width * height;
    }
    
    @Override
    public int compareTo(Object other) {
        Rectangle otherRect = (Rectangle) other;
        if (this.getArea() < otherRect.getArea())
            return -1;
        else if (this.getArea() > otherRect.getArea())
            return 1;
        else
            return 0;
    }
}

public class RectangleTest {
    public static void main(String[] args) {
        Rectangle r1 = new Rectangle(100, 30);
        Rectangle r2 = new Rectangle(200, 10);
        int result = r1.compareTo(r2);
        if (result == 1)
            System.out.println(r1 + "가 더 큼");
        else if (result == 0)
            System.out.println("같음");
        else
            System.out.println(r2 + "가 더 큼");
    }
}

 

13. 중첩 클래스

- 클래스 안에서 클래스 정의

- 정적 중첩 클래스: 앞에 static이 붙어서 내장되는 클래스

- 비정적 중첩 클래스: static이 붙지 않은 일반적인 중첩 클래스

    - 내부 클래스(inner class): 클래스의 멤버처럼 선언되는 중첩 클래스

    - 지역 클래스(local class): 메소드의 몸체 안에서 선언되는 중첩 클래스

    - 익명 클래스(anonymouse class): 수식의 중간에서 선언되고 바로 객체화되는 클래스

 

13-1. 내부 클래스

- 클래스 안에 클래스를 선언하는 경우

- 내부 클래스는 외부 클래스의 인스턴스 변수와 메소드 전부 사용 가능

 

13-2. 지역 클래스

- 메소드 안에 정의되는 클래스

- 메소드 안에서만 사용 가능

 

13-3. 중첩 클래스 사용하는 이유

- 내부 클래스는 외부 클래스의 private 멤버도 접근할 수 있음

 

13-4. 익명 클래스

- 클래스 몸체는 정의되지만 이름이 없는 클래스

- 클래스를 정의하면서 동시에 객체 생성

- 이름이 없기 때문에 한번만 사용 가능

- 부모클래스 참조변수 = new 부모클래스 () { .. }

 

public interface RemoteControl {
    void turnOn();
    void turnOff();
}

public class AnonymousClassTest {
    public static void main(String[] args) {
        // 익명 클래스 정의
        RemoteControl ac = new RemoteControl() {
            public void turnOn() {
                System.out.println("TV turnOn()");
            }
            public void turnOff() {
                System.out.println("TV turnOff()");
            }
        }
        ac.turnOn();
        ac.turnOff();
    }
}

 

'Software > JAVA' 카테고리의 다른 글

[JAVA] Day8. 자바 GUI 기초  (2) 2023.01.08
[JAVA] Day7. 자바 API 패키지, 예외처리, 모듈  (0) 2023.01.02
[JAVA] Day5. 상속  (0) 2022.12.29
[JAVA] Day 3-4. 클래스와 객체  (2) 2022.12.29
[JAVA] Day2. 조건문, 반복문, 배열  (0) 2022.12.27

+ Recent posts