Chapter 1: 서브 클래스 작성
- 클래스 확장
- 슈퍼 클래스 멤버에 엑세스
- 슈퍼 클래스 생성자 호출
Chapter2: 메소드 구현
- 가상 메소드(Virtual Method)
- 메소드 오버라이딩
- final 메소드
- final 클래스
Chapter 3: 인터페이스
- 인터페이스 선언
- 다중 인터페이스 구현
- 인터페이스 메소드 구현
- 인터페이스의 default 메소드
- 인터페이스의 static 메소드 구현
Chapter 4: 추상 클래스
- 추상 클래스 선언
- 클래스 계층 구조에서 추상 클래스 사용
- 클래스 계층 구조에서 추상 클래스 사용(2)
- 추상클래스와 인터페이스
- 추상 메소드 구현
Lab 10-1: 상속을 사용하여 인터페이스 구현
Chapter 1: 서브 클래스 작성
클래스 확장
- 한 클래스(Super class)에서 파생되는 클래스(Sub class)를 생성.
- 파생되는 Sub class는 Super class의 대부분의 요소를 상속. (생성자/소멸자 제외)
- 파생되는 Sub class는 Super class보다 더 공개적이다.
ex) Super class가 protected로 선언되면, Sub class는 public/protected는 가능하지만 default/private 불가능.
class Product { // Product -> Super class
...
}
class IDCard extends Product { // IDCard -> Sub class
...
}
슈퍼 클래스 멤버에 엑세스
- protected 멤버는 암시적으로 파생된 클래스에 상속.
- 파생된 클래스의 메소드에서 상속된 protected 멤버에 access 할 수 있다.
(같은 패키지 or 상속관계면 access가능, 다른 패키지 or 상속 관계가 아닌 클래스는 private 멤버처럼 동작)
/* 같은 패키지 or 상속 관계에 있는 클래스 access O */
class SuperClass {
protected String name;
}
class SubClass extends SuperClass {
}
class FurtherSubClass extends SubClass {
void success() {
System.out.println(name); // Okay
}
}
/* 다른 패키지 or 상속 관계가 없는 클래스 access X */
class Product {
...
protected String name;
}
class IDCard extends Product {
...
public String getTitle() {
return name;
}
}
class External {
void access(Product product) {
product.name; // 컴파일시 오류
}
}
슈퍼 클래스 생성자 호출
- Super class 생성자는 반드시 super 키워드를 사용해서 호출.
- private 생성자는 sub class에서 access 할 수 없다.
- super 키워드로 식별자 범위 한정. ex) super.name
class Product {
protected Product(String name)
...
}
class IDCard extends Product {
public IDCard(String name) {
super(name);
}
}
Chapter2: 메소드 구현
Sub class에서 Super class의 method를 재정의할 수 있다. -> override(오버라이딩)
가상 메소드(Virtual Method)
- 클래스 계층구조 내에서 같은 시그니처로 하위 클래스에서 재정의(오버라이딩) 할 수 있는 메소드.
- 객체지향 프로그램밍의 다형성에서 아주 중요한 부분.
- Java의 모든 메소드는 가상 메소드로 동작. (virtual 메소드만 override 가능)
메소드 오버라이딩
- Sub class에서 Super class의 메소드와 같은 시그니처로 정의.
- Sub class에서 오버라이드하는 메소드는 Super class의 가상 메소드보다 낮은 가시성을 가질 수 없다.
(super class에서 public으로 선언됐으면, sub class에서 public보다 낮은 default, priavte ... 불가능하다)
class Product {
public String getName() {
return "Product";
}
}
public class IDCard extends Product {
public String getName() {
return "IDCard";
}
}
Product product = new Product();
IDCard iDCard = new IDCard();
System.out.println(product.getName()); // “Product”
System.out.println(iDCard.getName()); // “IDCard”
final 메소드
- final 로 선언된 메소드는 Sub class에서 Override 할 수 없다.
/* final로 선언된 메소드 상속 불가. */
class Product {
final String getName() {
return "Product";
}
}
class IDCard extends Product {
public String getName() { // 컴파일 시 오류
return "IDCard";
}
}
/* super class의 final로 선언된 메소드를 sub class는 상속. */
class Product {
final String getName() {
return "Product";
}
}
class IDCard extends Product {
}
IDCard idCard = new IDCard();
idCard.getName(); // “Product”
final 클래스
- Super class로 동작되도록 설계하지 않은 클래스를 파생하는 것은 위험.
- final로 선언된 클래스에서는 sub class를 파생할 수 없다.
- Java의 String, StringBuilder 등의 클래스는 final로 선언됨.
/* final Class는 상속 불가 */
public final class Product {
final String getName() {
return "Product";
}
}
class IDCard extends Product { // 컴파일시 오류
}
Chapter 3: 인터페이스
인터페이스 선언
- interface 키워드를 사용하여 선언.
- interface는 선언만 하고, 구현(implements)은 sub에서 한다.
/* interface 예시 */
interface BinaryOp { // interface: 선언만 한다.
void apply(int right, int left);
}
class Adder implements BinaryOp { // 구현 한다.
public int apply(int right, int left) {
...
}
}
다중 인터페이스 메소드 구현
- 클래스는 하나 이상의 interface를 구현(implements)할 수 있다. (Java는 단일 상속만 허용하지만 예외다.)
- 인터페이스는 하나 이상의 인터페이스를 확장할 수 있다.
- 클래스는 interface의 모든 추상 메소드(구현되지 않은 메소드)를 반드시 구현해야 한다.
interface Flyable {
void fly();
}
interface Sucklable {
void suckle();
}
class Bat implements Flyable, Sucklable { // 2개의 interface를 implements함.
void fly() { ... }
void suckle() { ... }
}
인터페이스 메소드 구현
- 구현되는 메소드는 interface의 메소드와 시그니처가 같아야 한다.
- 구현 메소드 역시 가상 메소드로, 파생되는 클래스에서 오버라이드 할 수 없다.
- 클래스에서 구현되는 메소드는 interface의 추상 메소드(구현되지 않은 메소드)보다 좁은 가시성을 가질 수 없다.
(클래스가 interface의 메소드를 구현할 때, access level을 interface에 선언된 메소드보다 좁게 설정할 수 없다)
// 접근 제한은 interface보다 좁게 X, return 타입/이름/파라미터 목록이 같아야 한다.
interface Attackable {
int Attack(int power, String targetName);
}
class Tank implements Attackable {
public int Attack(int power, String targetName) { … }
public int Attack(String targetName, int power) { … } // 컴파일시 오류
}
인터페이스의 default 메소드
- Java에서 type을 정의하는 4가지: class, abstract class, interface, enum
- default 메소드는 interface에 기본 구현을 제공.
설명)
interface에 새로운 메소드를 추가해야 할 때, 기존에 해당 interface를 implements한 모든 클래스들이 해당 메소드를 구현해야하는 문제가 발생함. (interface를 implements 하려면 interface에서 요구하는 모든 메소드를 구현해야함)
이를 해결하기 위해, default method는 interface에 기본 구현을 제공할 수 있게 한다. 이를 통해 새로운 메소드를 interface에 추가하면서도, 기존의 서브타입들에게 영향을 주지 않는다.
interface InterfaceWithDefaultMethod {
void aMethod(); // 일반 추상 메소드
void default Method() { ... } // default 메소드
}
- default 메소드: 두 가지 패턴을 사용하여 활용 가능.
- Optional Method 패턴: interface에 메소드를 정의하되, implements가 이를 선택적으로 구현할 수 있게함.
(기존 interface에 새로운 메소드를 추가하면서 기존 implements에 미치는 영향을 최소화 ex. Iterator) - Multiple Inheritance of Behavior: interface가 다양한 default method를 제공.
(여러 interface에서 제공하는 default method들을 조합하여 사용.)
- Optional Method 패턴: interface에 메소드를 정의하되, implements가 이를 선택적으로 구현할 수 있게함.
인터페이스의 static 메소드 구현
- interface에서 static 메소드를 구현 후 사용. (클래스와 방법은 동일)
- 호출시 메소드 전체 이름을 사용.
/* interface에서 static method 정의 */
public interface MathUtils {
// 정적 메소드 정의
static int add(int a, int b) {
return a + b;
}
static int subtract(int a, int b) {
return a - b;
}
}
/* MathUtils interface의 instance 없이 호출 가능 */
public class Main {
public static void main(String[] args) {
// 인터페이스의 정적 메소드 호출
int sum = MathUtils.add(5, 3);
int difference = MathUtils.subtract(5, 3);
System.out.println("Sum: " + sum); // 출력: Sum: 8
System.out.println("Difference: " + difference); // 출력: Difference: 2
}
}
Chapter 4: 추상 클래스
공통적인 메소드나 데이터들을 구현해서 파생하는 클래스.
추상 클래스 선언
- 클래스 instance를 생성할 수 없다.
- 선언이 아닌 구현(코드)을 상속하는 형태로 사용.
- abstract 키워드를 사용해서 선언.
/* abstract class는 instance를 생성할 수 없다 */
abstract class Factory {
...
}
class Test {
public static void main(String[] args) {
Factory factory = new Factory(); // 컴파일시 오류
}
}
클래스 계층 구조에서 추상 클래스 사용
interface의 추상 메소드인 move를 추상 클래스인 Unit에서 구현해서, sub class인 Tank가 move()를 오버라이드 할 수 있다.
interface Moveable {
void move(int x, int y);
}
public abstract class Unit implements Moveable {
protected String name;
protected int x;
protected int y;
public String getName() {
return this.name;
}
public void move(int x, int y) {
this.x = x;
this.y = y;
}
}
class Tank extends Unit {
public void move(int x, int y) {
System.out.println("Now Moving");
}
}
클래스 계층 구조에서 추상 클래스 사용(2)
추상 클래스는 StringInstrument는 interface를 구현하지 않음. 그래서 sub class가 interface의 추상 메소드들을 구현해야함.
interface Instrument {
void play();
void tune();
}
public abstract class StringInstrument {
String name;
int numberOfString;
}
public class Guitar extends StringInstrument implements Instrument {
public void play() {}
public void tune() {}
}
추상클래스와 인터페이스
- 유사점
- instance화 될 수 없다: 객체로 생성되어 사용할 수 없다.
- final로 선언될 수 없다: interface와 추상 클래스는 파생되기 위한 용도이기 때문이다.
- 차이점
- interface는 같은 타입으로서의 구현을 강제.
- 추상 클래스는 데이터와 구현(코드)를 상속하고 확장을 유도.
- interface는 interface 외에는 확장할 수 없다.
추상 메소드 구현
- 추상 클래스(abstract class)에 추상 메소드(구현이 없는 메소드) 선언.
- abstract 키워드 사용
- 추상 클래스에서만 추상 메소드를 선언할 수 있다.
- 추상 메소드는 구현을 포함할 수 없다.
public abstract class StringInstrument {
String name;
int numberOfString;
// 추상 메소드 선언, 구현은 포함될 수 없다.
public abstract void changeString();
}
public class Guitar extends StringInstrument {
// sub class는 super class의 추상 메소드를 반드시 구현해야함.
public void changeString() { ... }
}
Lab 10-1: 상속을 사용하여 인터페이스 구현
2024.08.31 - [코딩 문제] - [연습 문제] 상속을 사용하여 인터페이스 구현
[연습 문제] 상속을 사용하여 인터페이스 구현
Adder와 Multiplier는 두 숫자를 인자로 받아 연산하는 같은 행위(Common Behavior)를 수행한다. 이 공통된 행위를 interface로 만든다.(BinaryOp) 그 후 Adder와 Multiplier는 이를 implements 한다. 코드BinaryOp.javainterf
lightningtech.tistory.com
출처: https://github.com/gikpreet/class-programming_with_java/tree/master
GitHub - gikpreet/class-programming_with_java
Contribute to gikpreet/class-programming_with_java development by creating an account on GitHub.
github.com
'Java' 카테고리의 다른 글
[Java] 11. Generics(제네릭) (0) | 2024.08.31 |
---|---|
[Java] Singleton 패턴 (0) | 2024.08.31 |
[Java] 09. 객체 생성과 제거 (0) | 2024.08.30 |
[Java] Getter / Setter 메소드 (0) | 2024.08.28 |
[Java] 08. 참조 타입 (2) | 2024.08.28 |