상속
상속 - 자식 클래스가 부모 클래스의 기능을 그대로 물려받을 수 있는 기능, extends를 사용해 클래스 상속을 한다
* 부모 클래스를 상속받은 자식 클래스는 부모 클래스의 기능에 더하여 더 많은 기능을 갖도록 할 수 있다
IS-A 관계
객체 지향 프로그래밍에서 상속 관계를 설명하는 개념 (ex. Dog 클래스가 Animal 클래스를 상속받으면, Dog는 Animal의 하위 개념이 됨)
-> 자식 클래스의 객체는 부모 클래스의 자료형으로 사용할 수 있다
Object 클래스
자바의 모든 클래스는 자동으로 Object 클래스를 상속받는다.
-> 자바에서 생성되는 모든 클래스는 Object 자료형으로 사용할 수 있다
메서드 오버라이딩
부모 클래스의 메서드를 자식 클래스가 동일한 형태로 또 다시 구현하는 행위
메서드 오버로딩
이름이 같고 매개변수가 다른 메서드를 여러개 정의하는 것을 메서드 오버로딩이라 한다
메서드의 이름이 같아도 매개변수의 타입 및 순서가 다르면 오버로딩을 할 수 있다
* 자바는 다중 상속을 지원하지 않는다
생성자
객체 변수에 값을 무조건 설정해야만 객체가 생성될 수 있도록 강제할 때 사용
생성자의 규칙
- 클래스명과 메서드명이 같다
- 리턴 타입을 정의하지 않는다 (void도 사용하지 않는다)
new 클래스명(입력인수, ...) // new 키워드가 사용될 때 생성자가 호출된다
디폴트 생성자
생성자의 입력 항목이 없고 생성자 내부에 아무 내용이 없는 생성자
클래스에 생성자가 하나도 없으면 자동으로 컴파일러가 디폴트 생성자를 추가함
생성자 오버로딩
입력 항목이 다른 생성자를 여러 개 만드는 것
인터페이스
인터페이스 - 일종의 규칙으로, 클래스들이 특정 메서드를 반드시 구현하도록 강제
인터페이스를 사용하면 한 번의 구현으로 다양한 상황에 대처할 수 있음
Predator 인터페이스를 만들어서 getFood()라는 메서드를 정의한 후, 이를 구현하는 모든 클래스에서 이 메서드를 반드시 구현하게 만들 수 있다
interface Predator {
String getFood();
}
class Tiger extends Animal implements Predator {
public String getFood() { return "apple"; }
}
class Lion extends Animal implements Predator {
public String getFood() { return "banana"; }
}
ZooKeeper 클래스는 이제 feed 메서드를 하나만으로 다양한 육식동물을 처리할 수 있다
class ZooKeeper {
void feed(Predator predator) {
System.out.println("feed " + predator.getFood());
}
}
새로운 육식동물이 추가되더라도 해당 클래스가 Predator 인터페이스를 구현하면 feed 메서드를 변경할 필요가 없다
디폴트 메서드
자바 8 이후로 인터페이스는 default 키워드를 사용해 기본 구현이 포함된 메서드를 가질 수 있다.
-> 인터페이스를 구현하는 클래스에서 선택적으로 오버라이딩할 수 있다.
interface Predator {
String getFood();
default void printFood() {
Systehttp://m.out.printf("my food is %s\n", getFood());
}
}
다형성
객체 지향 프로그래밍에서 다형성은 동일한 메서드가 다양한 방식으로 동작할 수 있도록 하는 기능
코드의 유연성과 확장성을 높이며, 복잡한 조건문을 줄여 가독성과 유지보수를 용이하게 한다.
class Bouncer {
void barkAnimal(Animal animal) {
if (animal instanceof Tiger) {
System.out.println("어흥");
} else if (animal instanceof Lion) {
System.out.println("으르렁");
}
}
}
Bouncer 클래스는 instanceof 를 사용하여 객체 타입을 검사하고 각 타입에 맞는 출력을 한다
-> 새로운 동물 클래스가 추가될 때마다 조건문을 추가해야 하므로 비효율적
인터페이스를 활용한 개선
interface Barkable {
void bark();
}
class Tiger extends Animal implements Barkable {
public void bark() {
System.out.println("어흥");
}
}
class Lion extends Animal implements Barkable {
public void bark() {
System.out.println("으르렁");
}
}
class Bouncer {
void barkAnimal(Barkable animal) {
animal.bark();
}
}
Bouncer 클래스는 barkAnimal 메서드에서 Barkable 인터페이스를 통해 bark() 메서드만 호출하면 된다
-> 새로운 동물이 추가될 때 Barkable 인터페이스를 구현하면 Bouncer 코드를 수정할 필요가 없다
* 객체의 선언된 자료형에 따라 사용할 수 있는 메서드가 제한된다. Barkable로 선언된 객체는 bark() 메서드만 사용할 수 있음
인터페이스 상속
interface BarkablePredator extends Predator, Barkable {}
class Lion extends Animal implements BarkablePredator {
public void bark() {
System.out.println("으르렁");
}
public String getFood() {
return "banana";
}
}
BarkablePredator라는 인터페이스를 통해 두 개의 인터페이스를 상속받아 두 기능 모두 구현 가능
추상 클래스
추상 클래스 - 인터페이스 역할도 하면서 클래스의 기능도 가지고 있음, class앞과 인터페이스의 메서드와 같은 역할을 하는 메서드에 abstract 표기
* 일반 클래스와 달리 단독으로 객체 생성 불가
* 인터페이스와 달리 일반 클래스처럼 객체 변수, 생성자, private 메서드 등을 가질 수 있다
Quiz
1. 자바에서 한 클래스가 다른 클래스를 상속받을 때 사용하는 키워드는 무엇인가요?
답 - b) extends
2. 상속을 통해 자식 클래스가 부모 클래스에서 얻을 수 있는 이점은 무엇인가요?
답 - a) 코드 재사용성
3. 다중 상속이 허용되지 않는 이유 중 하나는 무엇인가요?
답 - c) 다이아몬드 문제로 인한 모호성
4. 상속된 메서드를 자식 클래스에서 재정의하려면 어떤 키워드를 사용하나요?
답 - d) 없음, 자동으로 재정의된다.
5. 자바에서 모든 클래스의 상위 클래스는 무엇인가요?
답 - a) Object
6. 생성자의 기본 역할은 무엇인가요?
답 - b) 클래스의 객체를 초기화한다.
7. 생성자는 언제 호출되나요?
답 - b) 객체가 생성될 때
8. 생성자를 오버로딩할 때 중요한 조건은 무엇인가요?
답 - b) 서로 다른 매개변수를 가져야 한다
9. 인터페이스의 특징으로 옳은 것은 무엇인가요?
답 - b) 메서드의 구현을 포함할 수 없다
10. 인터페이스의 메서드 구현을 클래스에서 강제하기 위한 키워드는 무엇인가요?
답 - a) implements
11. 다형성의 주요 특징은 무엇인가요?
답 - c) 동일한 인터페이스로 다양한 구현을 사용할 수 있다
12. 오버라이딩과 오버로딩의 차이점으로 올바른 것은 무엇인가요?
답 - c) 오버라이딩은 상속 관계에서 이루어진다
13. 추상 클래스의 주요 특징으로 옳은 것은 무엇인가요?
답 - c) 인스턴스를 만들 수 없다
14. 추상 클래스와 인터페이스의 공통점은 무엇인가요?
답 - a) 둘 다 객체를 생성할 수 없다
15. 추상 메서드는 어떤 키워드를 사용하여 선언하나요?
답 - c) abstract
서술형 문제
1. 추상 클래스와 일반 클래스의 차이점을 설명하세요.
답 - 추상 클래스는 인스턴스를 생성할 수 없고 추상 메서드를 가질 수 있는 클래스이며, 일반 클래스는 인스턴스 생성이 가능하고 모든 메서드가 구현되어야 한다.
2. 추상 클래스와 인터페이스를 함께 사용하는 이유와 예를 설명하세요.
답 - 추상 클래스와 인터페이스를 함께 사용하면 클래스 계층에서 공통 기능(추상 클래스)과 다중 기능 구현(인터페이스)을 모두 활용할 수 있다.
3. 추상 클래스를 상속받은 자식 클래스에서 추상 메서드를 구현해야 하는 이유를 설명하세요.
답 - 자식 클래스는 부모 추상 클래스의 추상 메서드를 구현해야 클래스가 완전해지고 객체로 생성될 수 있다.
4. 추상 클래스에서 선언된 일반 메서드와 추상 메서드의 차이점을 설명하세요.
답 - 추상 클래스의 일반 메서드는 구현된 메서드이며, 추상 메서드는 구현 없이 선언만 되어 자식 클래스에서 구현해야 한다.
5. 상속과 구성(Composition)의 차이점과 각각의 장단점을 비교하세요.
답 - 상속은 클래스 간 IS-A 관계를 나타내며 코드 재사용이 쉽지만 유연성이 떨어지며, 구성은 유연성이 높고 의존성을 줄일 수 있다.
6. 생성자에서 this와 super 키워드의 차이점에 대해 설명하세요.
답 - this는 현재 클래스의 인스턴스를 참조하며, super는 부모 클래스의 멤버를 참조한다.
7. 자바에서 인터페이스와 추상 클래스의 차이점을 설명하세요.
답 - 인터페이스는 다중 상속이 가능하고 모든 메서드가 기본적으로 추상적이며, 추상 클래스는 단일 상속만 가능하고 추상 메서드와 일반 메서드를 같이 가질 수 있다.
8. 다형성의 개념과 객체지향 프로그래밍에서의 중요성을 설명하세요.
답 - 다형성은 객체가 여러 타입으로 참조될 수 있는 성질이며, 객체지향 프로그래밍에서 코드의 유연성과 확장성을 높인다.
9. 메서드 오버로딩과 오버라이딩의 차이점을 비교하세요.
답 - 메서드 오버로딩은 같은 이름의 메서드를 매개변수로 구분하며, 오버라이딩은 부모 클래스의 메서드를 자식 클래스에서 재정의한다.
10. 동적 바인딩의 개념을 설명하고 다형성과의 관계를 설명하세요.
답 - 동적 바인딩은 실행 시점에 메서드 호출이 결정되는 것을 의미하며, 다형성을 통해 상속받은 메서드를 동적으로 호출할 수 있게 한다.
코딩테스트 문제
1.
class Animal {
String sound = "generic sound";
}
class Dog extends Animal {
String sound = "bark";
}
public class Main {
public static void main(String[] args) {
Animal a = new Dog();
System.out.println(a.sound);
}
}
generic sound
2.
class Parent {
void show() {
System.out.println("Parent");
}
}
class Child extends Parent {
void show() {
System.out.println("Child");
}
}
public class Main {
public static void main(String[] args) {
Parent p = new Child();
p.show();
}
}
Child
3.
class Parent {
int x = 10;
}
class Child extends Parent {
int x = 20;
}
public class Main {
public static void main(String[] args) {
Parent p = new Child();
System.out.println(p.x);
}
}
10
4.
class A {
A() {
System.out.println("A's constructor");
}
}
class B extends A {
B() {
System.out.println("B's constructor");
}
}
public class Main {
public static void main(String[] args) {
B obj = new B();
}
}
A's constructor
B's constructor
5.
class A {
A() {
System.out.println("A's no-arg constructor");
}
}
class B extends A {
B() {
System.out.println("B's no-arg constructor");
}
}
public class Main {
public static void main(String[] args) {
A a = new B();
}
}
A's no-arg constructor
B's no-arg constructor
6.
interface A {
void display();
}
interface B extends A {
void display();
}
class C implements B {
public void display() {
System.out.println("C's display");
}
}
public class Main {
public static void main(String[] args) {
A obj = new C();
obj.display();
}
}
C's display
7.
interface A {
default void show() {
System.out.println("A");
}
}
class B implements A {
public void show() {
System.out.println("B");
}
}
public class Main {
public static void main(String[] args) {
A obj = new B();
obj.show();
}
}
B
'WINK-(Web & App) > JAVA 스터디' 카테고리의 다른 글
[2024-2 Java 스터디] 강보경 #4주차 (2) | 2024.11.07 |
---|---|
[2024-2 Java 스터디] 김태일 #4주차 (0) | 2024.11.06 |
[2024-2 Java 스터디] 김지나 #4주차 "5.5~5.9" (0) | 2024.11.06 |
[2024-2 Java 스터디] 정채은 #3주차 (0) | 2024.10.31 |
[2024-2 Java 스터디] 김재승 #3주차 (0) | 2024.10.31 |