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 |