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);
}
}
...
class Dog extends Animal {
void sleep() {
System.out.println(this.name+" zzz");
}
}
...
is a
AnimalAnimal dog = new Dog();
// 개로 만든 객체는 동물의 자료형이다.
Object 클래스
- 모든 클래스는 object 클래스를 상속 받는다.
- 굳이 상속하도록 하지 않아도 자동 상속 받는다.
- 그러므로 모든 객체는 object의 자료형으로 사용 가능하다.
Object animal = new Animal(); // Animal is a Object Object dog = new Dog(); // Dog is a Object
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");
}
}
...
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");
}
}
...
Constructor
HouseDog dog = new HouseDog();
System.out.println(dog.name);
// null
class HouseDog extends Dog {
HouseDog(String name) {
this.setName(name);
}
...
HouseDog dog = new HouseDog("뭉뭉이");
// 생성자 호출 시 문자열을 전달해야 한다.
// HouseDog dog = new HouseDog(); -> error
생성자 규칙
1. 클래스명과 메서드명 동일
2. 리턴 타입 정의 놉! (void도 놉!)생성자 호출
new 클래스명 (입력인수, ...)
class HouseDog extends Dog {
HouseDog() {
}
HouseDog(String name) {
this.setName(name);
}
...
...
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); // 숫자로 생성
System.out.println(happy.name);
// happy 출력
System.out.println(yorkshire.name);
// yorkshire 출력
// new HouseDog(2)로 한다면 bulldog 출력
인터페이스가 필요한 이유
난 동물원의 사육사이다. 육식동물이 들어오면 난 먹이를 던져준다. 호랑이가 오면 사과를 던져준다. 사자가 오면 바나나를 던져준다.
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 출력 } }
implements
interface Predator {
}
...
class Tiger extends Animal implements Predator {
}
class Lion extends Animal implements Predator {
}
...
class ZooKeeper {
void feed(Predator predator) {
System.out.println("feed apple"); // 항상 apple 출력
}
}
...
public
으로interface Predator {
String getFood();
}
...
class Tiger extends Animal implements Predator {
public String getFood() { // 구현은 public
return "apple";
}
}
class Lion extends Animal implements Predator {
public String getFood() { // 구현은 public
return "banana";
}
}
...
class ZooKeeper {
void feed(Predator predator) {
System.out.println("feed "+predator.getFood());
// 각 클래스에 구현된 내용이 출력됨
}
}
...
상속을 통해서 사용해도 동일한 효과
Animal 클래스에 getFood 메서드 추가 하고, Tiger, Lion 등에서 getFood 오버라이딩 한 후, Zookeeper의 feed 메서드가 Animal의 자료형으로 사용
하지만, 상속을 통해서 한다면 해당 메서드를 반드시 구현해야 한다는 강제성을 갖지 못한다.
이처럼 인터페이스는 인터페이스의 메서드를 반드시 구현해야 하는
강제성
을 갖는다
interface Predator {
String getFood();
default void printFood() {
System.out.printf("my food is %s\n", getFood());
}
}
인터페이스명.스태틱메서드명
interface Predator {
...
int LEG_COUNT = 4; // 인터페이스 상수
static int speed() {
return LEG_COUNT * 30;
}
}