05-5 상속
- 상속 : 자식 클래스가 부모 클래스의 기능을 그대로 물려받는 것
- extends 키워드를 사용하여 상속
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Dog extends Animal { // Animal 클래스를 상속한다.
}
public class Sample {
public static void main(String[] args) {
Dog dog = new Dog();
dog.setName("poppy");
System.out.println(dog.name);
}
}
1. 자식 클래스의 기능 확장하기
- Dog 클래스에 sleep 메서드를 추가
class Dog extends Animal {
void sleep() {
System.out.println(this.name+" zzz");
}
}
2. IS-A 관계
- Dog 클래스가 Animal 클래스에 상속됨 -> Dog is a Animal 과 같이 말할 수 있는 관계 == IS-A 관계
- 자식클래스의 객체는 부모 클래스의 자료형인 것처럼 사용 가능
Animal dog = new Dog();
- 반대의 경우에는 컴파일 오류가 남
Dog dog = new Animal(); // 컴파일 오류
3. 메서드 오버라이딩
- 같은 메서드를 다른 클래스에 구현
- sleep메서드를 HouseDog 클래스에 추가해주어 우선순위에 따라 HouseDog 클래스의 sleep 메서드가 호출함
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Dog extends Animal {
void sleep() {
System.out.println(this.name + " zzz");
}
}
class HouseDog extends Dog {
void sleep() {
System.out.println(this.name + " zzz in house");
}
}
public class Sample {
public static void main(String[] args) {
HouseDog houseDog = new HouseDog();
houseDog.setName("happy");
houseDog.sleep(); // happy zzz in house 출력
}
}
4. 메서드 오버로딩
- 메서드 이름은 동일하지만 메서드의 입력 항목이 다른 경우
class HouseDog extends Dog {
void sleep() {
System.out.println(this.name + " zzz in house");
}
void sleep(int hour) {
System.out.println(this.name + " zzz in house for " + hour + " hours");
}
}
5. 다중 상속이란?
- 다중 상속 : 클래스가 동시에 하나 이상의 클래스를 상속받는 것
- 자바에서는 불가능 -> 어떤 클래스가 우선순위인지 모르기 때문에 불명확함
class A {
public void msg() {
System.out.println("A message");
}
}
class B {
public void msg() {
System.out.println("B message");
}
}
class C extends A, B {
public void static main(String[] args) {
C test = new C();
test.msg();
}
}
05-6 생성자
- 객체 변수에 값을 무조건 설정해야만 객체가 생성될 수 있도록 강제하는 것
- 생성자 규칙
- 클래스명과 메서드명이 같다
- 리턴 타입을 정의하지 않는다 (void도 사용하지 않음)
...
class HouseDog extends Dog {
HouseDog(String name) {
this.setName(name); // name 객체 변수에 값 설정
}
}
public class Sample {
public static void main(String[] args) {
HouseDog dog = new HouseDog("happy");
System.out.println(dog.name);
}
} //happy 출력
1. 디폴트 생성자
- 디폴트 생성자 : 입력 항목이 없고, 내부가 비어있는 생성자
- Dog 클래스의 객체가 만들어질때 디폴트 생성자 Dog() 실행
class Dog extends Animal {
Dog() {
}
void sleep() {
System.out.println(this.name + " zzz");
}
}
2. 생성자 오버로딩
- 입력값을 다르게하여 메서드와 마찬가지로 오버로딩이 가능
class HouseDog extends Dog {
HouseDog(String name) {
this.setName(name);
}
HouseDog(int type) {
if (type == 1) {
this.setName("yorkshire");
} else if (type == 2) {
this.setName("bulldog");
}
}
}
HouseDog happy = new HouseDog("happy"); // 문자열로 생성
HouseDog yorkshire = new HouseDog(1); // 숫자값으로 생성
05.7 인터페이스
- interface 키워드로 작성
- 다른 클래스를 작성할 때 기본이 되는 틀 제공
- 클래스 사이의 중간 매개 역할을 담당하는 추상 클래스 (다중 상속 지원)
- implements로 상속 가능
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Tiger extends Animal {
}
class Lion extends Animal {
}
class ZooKeeper {
void feed(Tiger tiger) { // 호랑이가 오면 사과를 던져 준다.
System.out.println("feed apple");
}
void feed(Lion lion) { // 사자가 오면 바나나를 던져준다.
System.out.println("feed banana");
}
}
public class Sample {
public static void main(String[] args) {
ZooKeeper zooKeeper = new ZooKeeper();
Tiger tiger = new Tiger();
Lion lion = new Lion();
zooKeeper.feed(tiger); // feed apple 출력
zooKeeper.feed(lion); // feed banana 출력
}
}
위와 같은 코드를 작성할 때 동물이 추가될 때마다 ZooKeeper클래스의 오버로딩되는 메서드가 추가될 것이다.
이 코드를 간편화하기 위해서 interface를 사용하면 다음과 같이 변한다.
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";
}
...
class ZooKeeper {
void feed(Predator predator) {
System.out.println("feed" + Predator.getFood());
}
}
ZooKeeper의 코드가 훨씬 간단화된것을 볼 수 있다.
※ ZooKeeper 클래스가 동물 클래스에 의존적인 클래스에서 동물 클래스와 상관없는 독립적인 클래스가 되었다는 점이 핵심!!
05-8 다형성
동물 울음소리를 출력하는 Bouncer 클래스를 만들어보자
class Bouncer {
void barkAnimal(Animal animal) {
if (animal instanceof Tiger) {
System.out.println("어흥");
} else if (animal instanceof Lion) {
System.out.println("으르렁");
} else if (animal instanceof Crocodile) {
System.out.println("쩝쩝");
} else if (animal instanceof Leopard) {
System.out.println("캬옹");
}
}
}
동물들이 많아지면 if-else 문이 많아진다
위에서 했던대로 인터페이스를 사용하면,
interface Barkable {
void bark();
}
...
class Tiger extends Animal implements Predator, Barkable {
public void bark() {
System.out.println("어흥");
}
}
...
class Lion extends Animal implements Predator, Barkable {
public void bark() {
System.out.println("으르렁");
}
}
...
class Bouncer {
void barkAnimal(Barkable animal) { // Animal 대신 Barkable을 사용
animal.bark();
}
Bouncer클래스가 간단화된것을 볼 수 있다.
만약 Tiger tiger = new Tiger(); 를 통해 tiger객체를 만들면 이 객체는 여러개의 자료형 타입을 가진다.
이를 다형성이라고 한다.
05-9 추상 클래스
- 인터페이스의 역할도 하면서 클래스의 기능도 가지고 있는 클래스- 클래스 앞에 abstract로 표기
- 디폴트 메서드를 더 이상 사용할 수 없으므로 default 키워드를 삭제해야함
abstract class Predator extends Animal {
abstract String getFood();
void printFood() { // default 를 제거한다.
System.out.printf("my food is %s\n", getFood());
}
}
(... 생략 ...)
'Java' 카테고리의 다른 글
[2024-2 Java 스터디] #5주차 "콘솔, 파일 입출력" (0) | 2024.11.14 |
---|---|
4주차 퀴즈 (2) | 2024.11.06 |
3주차 퀴즈 (0) | 2024.10.31 |
[2024-2 Java 스터디] #3주차 "클래스, 메서드" (0) | 2024.10.30 |
2주차 퀴즈(2) (2) | 2024.10.15 |