추상클래스
추상 클래스란?
추상 클래스(Abstract Class)는 추상 메서드를 하나 이상 포함하거나, 객체를 직접 생성할 수 없고 다른 클래스에서 상속받아 사용하도록 설계된 클래스를 말함.
특징
1. 객체 생성 불가
- 추상 클래스 자체로는 객체를 생성할 수 없음.
- 반드시 상속받은 하위 클래스에서 구현하여 사용해야 함.
예)
abstract class Animal {
public abstract void sound();
}
Animal a = new Animal(); // 오류: 추상 클래스는 인스턴스화할 수 없음
2. 추상 메서드
- abstract 키워드로 선언된 메서드로, 구현부가 없는 메서드.
- 하위 클래스에서 반드시 오버라이딩(재정의) 해야 함.
예)
abstract class Animal {
public abstract void sound(); // 구현 없음
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("멍멍");
}
}
3. 일반 메서드 포함 가능
- 추상 클래스는 일반 메서드와 필드를 가질 수 있음.
- 상속받은 클래스에서 공통 기능을 구현하거나 데이터 초기화를 지원할 때 사용.
4. 상속의 기초
- 추상 클래스는 상속을 통해 하위 클래스의 공통 기능을 정의하는 데 적합.
5. abstract 키워드
- 클래스나 메서드에 abstract 키워드를 사용하여 선언.
- 추상 메서드는 반드시 구현 없이 선언만 가능.
추상 클래스 구현 예제
1. 기본 예제
abstract class Animal {
protected String name;
// 생성자
public Animal(String name) {
this.name = name;
}
// 추상 메서드
public abstract void sound();
// 일반 메서드
public void eat() {
System.out.println(name + "이(가) 먹이를 먹습니다.");
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void sound() {
System.out.println("멍멍");
}
}
class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void sound() {
System.out.println("야옹");
}
}
public class AbstractClassExample {
public static void main(String[] args) {
Animal dog = new Dog("강아지");
dog.sound(); // 멍멍
dog.eat(); // 강아지이(가) 먹이를 먹습니다.
Animal cat = new Cat("고양이");
cat.sound(); // 야옹
cat.eat(); // 고양이이(가) 먹이를 먹습니다.
}
}
2. 공통 기능 정의 및 확장
abstract class Shape {
protected String color;
public Shape(String color) {
this.color = color;
}
public abstract double getArea();
public String getColor() {
return color;
}
}
class Circle extends Shape {
private double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(String color, double width, double height) {
super(color);
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return width * height;
}
}
public class ShapeTest {
public static void main(String[] args) {
Shape circle = new Circle("Red", 5);
Shape rectangle = new Rectangle("Blue", 4, 6);
System.out.println("Circle Area: " + circle.getArea()); // Circle Area: 78.5398...
System.out.println("Rectangle Area: " + rectangle.getArea()); // Rectangle Area: 24.0
}
}
추상 클래스 사용 시점
- 클래스 간에 공통된 속성과 메서드가 있을 때.
- 일부 메서드는 공통으로 제공, 일부는 구현 강제가 필요할 때.
- 상속을 통해 구조를 정의하고 확장성 있는 프로그램을 만들고자 할 때.
인터페이스
인터페이스란?
인터페이스(Interface)는 클래스나 프로그램의 구조를 정의하는 데 사용되는 청사진으로, 클래스가 구현해야 하는 메서드들의 집합. 인터페이스를 구현한 클래스는 해당 인터페이스에 정의된 모든 메서드를 반드시 구현해야 함.
특징
- 추상 메서드의 집합
- 인터페이스에 선언된 메서드는 기본적으로 추상 메서드이며, 구현부가 없음.
- 구현 클래스에서 반드시 오버라이딩(재정의) 해야 함.
- 필드는 상수만 가능
- 인터페이스에서 선언된 필드는 public static final로 자동 지정됨.
- 값을 변경할 수 없는 상수만 가질 수 있음.
- 다중 구현 가능
- 한 클래스가 여러 개의 인터페이스를 implements 키워드로 구현 가능.
- Java에서 다중 상속의 제한을 해결하는 데 사용.
- implements 키워드
- 클래스를 선언할 때 implements 키워드를 사용해 인터페이스를 구현.
- Java 8 이후 변경 사항
- default 메서드: 구현 클래스에서 선택적으로 오버라이드할 수 있는 기본 구현을 가진 메서드.
- static 메서드: 객체 없이 인터페이스 자체에서 호출 가능한 메서드.
- 객체 생성 불가
- 인터페이스 자체로는 객체를 생성할 수 없으며, 구현 클래스를 통해 인스턴스화해야 함.
인터페이스 정의 및 구현 예제
1. 기본 인터페이스 정의와 구현
interface Animal {
// 추상 메서드
void sound();
// 상수
String CATEGORY = "동물";
}
class Dog implements Animal {
@Override
public void sound() {
System.out.println("멍멍");
}
}
class Cat implements Animal {
@Override
public void sound() {
System.out.println("야옹");
}
}
public class InterfaceExample {
public static void main(String[] args) {
Animal dog = new Dog();
dog.sound(); // 멍멍
Animal cat = new Cat();
cat.sound(); // 야옹
// 인터페이스 상수 사용
System.out.println(Animal.CATEGORY); // 동물
}
}
2. 다중 인터페이스 구현
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
class Duck implements Flyable, Swimmable {
@Override
public void fly() {
System.out.println("오리가 날아갑니다.");
}
@Override
public void swim() {
System.out.println("오리가 헤엄칩니다.");
}
}
public class MultiInterfaceExample {
public static void main(String[] args) {
Duck duck = new Duck();
duck.fly(); // 오리가 날아갑니다.
duck.swim(); // 오리가 헤엄칩니다.
}
}
Java 8 이후 추가 기능
1. default 메서드
- 기본 구현을 가지며, 구현 클래스에서 선택적으로 오버라이드 가능.
interface Device {
void turnOn();
default void turnOff() {
System.out.println("디바이스를 끕니다.");
}
}
class Phone implements Device {
@Override
public void turnOn() {
System.out.println("전화기를 켭니다.");
}
@Override
public void turnOff() {
System.out.println("전화기를 끕니다.");
}
}
public class DefaultMethodExample {
public static void main(String[] args) {
Device phone = new Phone();
phone.turnOn(); // 전화기를 켭니다.
phone.turnOff(); // 전화기를 끕니다.
}
}
2. static 메서드
- 인터페이스 이름을 통해 호출 가능.
interface Utility {
static void printInfo() {
System.out.println("Utility 인터페이스의 static 메서드입니다.");
}
}
public class StaticMethodExample {
public static void main(String[] args) {
Utility.printInfo(); // Utility 인터페이스의 static 메서드입니다.
}
}
언제 인터페이스를 사용할까?
- 서로 다른 클래스가 공통적으로 가져야 할 행동(기능)을 정의할 때.
- 다중 상속의 장점을 활용하고 싶을 때.
- 특정 행동(메서드)을 반드시 구현해야 하는 계약을 설정할 때.
추상 클래스와 인터페이스 차이
특징 | 추상 클래스 | 인터페이스 |
목적 | 공통된 기능 정의 및 상속 | 행동(기능) 정의 |
메서드 구현 | 추상 메서드와 일반 메서드 모두 포함 가능 | 구현 없이 메서드 선언만 가능 (Java 8 이후 default 지원) |
다중 상속 | 불가능 (extends 키워드 사용) | 가능 (implements 키워드 사용) |
extends vs implements | extends 키워드 사용 | implements 키워드 사용 |
필드 | 일반 필드와 상수 모두 사용 가능 | public static final 상수만 가능 |
Final
1. final 클래스
final 키워드는 클래스, 메소드, 필드에 사용될 수 있으며, 이를 통해 해당 요소가 변경되지 않도록 보장. final 클래스를 사용하면 해당 클래스를 상속할 수 없게 만듭니다. 즉, final 클래스는 다른 클래스의 부모가 될 수 없으며, 상속을 통한 클래스의 변경을 막습니다. 이는 클래스를 고정된 형태로 유지하려는 의도가 있음.
final class MyClass {
// 클래스 내용
}
...
class SubClass extends MyClass { // 오류 발생
// 상속 불가
}
1-1. Java JDK에서 final 클래스
Java의 표준 라이브러리에도 final 클래스를 많이 찾아볼 수 있음. 예를 들어, String 클래스는 final로 선언되어 있어 상속이 불가능합니다. 이를 통해 String 클래스가 불변(immutable) 속성을 유지하도록 보장함. String을 상속하면 불변성을 깨트릴 수 있기 때문에 상속을 허용하지 않습니다.
final class String {
// String 클래스는 상속 불가
}
2. final 필드
final로 선언된 필드는 값을 한 번만 할당할 수 있습니다. 즉, 초기화 이후에는 값을 변경할 수 없습니다. 주로 불변 객체를 만들 때 사용되며, 상수 값을 선언할 때 유용합니다.
public class MyClass {
final int MAX_VALUE = 100; // final 필드
public void changeValue() {
MAX_VALUE = 200; // 오류 발생: final 필드는 값을 변경할 수 없음
}
}
MAX_VALUE는 한 번 초기화된 후 값을 변경할 수 없음.
3. final 메소드
final 메소드는 오버라이딩을 할 수 없음. 즉, final로 선언된 메소드는 자식 클래스에서 재정의할 수 없으며, 부모 클래스에서 구현된 메소드의 동작을 그대로 사용할 수 있게 강제함. 이는 메소드의 기능을 변경하지 않도록 보장하려는 목적이 있습니다.
class ParentClass {
final void display() {
System.out.println("This is the final method.");
}
}
class ChildClass extends ParentClass {
@Override
void display() { // 오류 발생: final 메소드는 오버라이드할 수 없음
System.out.println("Overridden method.");
}
}
위 코드에서 display() 메소드는 final로 선언되어 있어 자식 클래스에서 오버라이딩할 수 없음.
이렇게 final은 클래스, 필드, 메소드에서 사용될 수 있으며, 변경 불가능한 요소를 만들거나 상속, 오버라이딩을 제한하는 등의 용도로 사용됨.
'멋쟁이사자처럼_부트캠프 > Java' 카테고리의 다른 글
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 10일차 내부 클래스, 익명 개체, 자주 사용되는 클래스, 제네릭 (4) | 2024.12.13 |
---|---|
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 9일차 예외 처리 (1) | 2024.12.13 |
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 7일차 헷갈릴수 있는 코드 정리, 클래스 내부 필드와 문자열 처리 방식의 차이점, String (4) | 2024.12.11 |
[상속]필드와 메서드의 차이 (2) | 2024.12.09 |
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 6일차 생성자, 상속, 오버라이딩과 오버로딩 (2) | 2024.12.09 |