260 likes | 657 Views
8. 인터페이스와 추상 클래스. 추상클래스 (1/5). Animal. Feline. Dog. Canine. Hippo. Wolf. Lion. Cat. Tiger. picture food hunger boundaries location. makeNoise () eat(). makeNoise () eat(). makeNoise () eat(). makeNoise () eat(). makeNoise () eat(). makeNoise () eat().
E N D
추상클래스 (1/5) Animal Feline Dog Canine Hippo Wolf Lion Cat Tiger picture food hunger boundaries location makeNoise() eat() makeNoise() eat() makeNoise() eat() makeNoise() eat() makeNoise() eat() makeNoise() eat() roam() roam() makeNoise() eat() sleep() roam() Head First JAVA
추상클래스 (2/5) Animal aWolf = new Wolf; Wolf 객체에 대한 Animal 레퍼런스 Animal Wolf 객체 Animal anim = new Animal(); Animal 객체에 대한 Animal 레퍼런스 aWolf anim Animal Animal 객체 이 둘도 같은 유형이지만 Animal 객체는 도대체 어떻게 생겼을까? Head First JAVA
추상클래스 (3/5) 클래스중에는 인스턴스(속성)를 만들면 안 되는 것도 있음 Ex> Wolf 객체, Hippo 객체, Tiger 객체 등은 이해가 되지만 Animal 객체는 정확하게 어떤 것인지 알 수 없다. abstract class Canine extends Animal { public void roam() { } } 클래스를 추상 클래스로 만든다 클래스를 선언할 때 앞에 abstract만 붙여줌 어떤 클래스의 인스턴스를 만들 수 없게 하는 방법 즉 특정 유형에 대해 ‘new’ 키워드를 쓸 수 없게 하는 방법 Head First JAVA
추상 클래스 (4/5) 추상 클래스 - 아무도 그 클래스의 새로운 인스턴스를 만들 수 없는 클래스 abstract public class Canine extends Animal { public void roam() { } } public class MakeCanine { public void go() { Canine c; c = new Dog(); c = new Canine(); c.roam(); } } 상위클래스가 추상 클래스인 경우에도 하위클래스 객체를 상위클래스 레퍼런스에 대입하는 것은 가능 Canine 클래스는 추상 클래스이기 때문에 이런 선언은 불가능 Head First JAVA
추상 클래스 (5/5) 추상 추상 구상 Tiger Lion Wolf Hippo Dog Canine Feline Animal Cat picture food hunger boundaries location 구상 makeNoise() eat() makeNoise() eat() makeNoise() eat() makeNoise() eat() makeNoise() eat() makeNoise() eat() roam() roam() 추상 makeNoise() eat() sleep() roam() 구상 구상 구상 구상 Head First JAVA
추상 메소드 추상 클래스는 반드시 확장해야 하는 클래스 → 추상 메소드는 반드시 오버라이드 해야 하는 메소드 적당한 코드를 생각할 수 없는 메소드를추상메소드로 만들기 때문에 몸통이 없음 추상 메소드를 만들 때는 클래스도 반드시 추상 클래스로 만들어야 함 - But 추상 클래스 안에 추상 메소드와 추상 메소드가 아닌 메소드를 집어 넣는 것은 가능 public abstract void eat(); Head First JAVA
다형성 예제 public class MyAnimalList { private Animal [] animals = new Animal[5]; private intnextIndex = 0; public void add(Animal a) { if (nextIndex < animals.length) { animals[nextIndex] = a; System.out.println(“Animal added at “ + nextIndex); nextIndex++; } } } public classAnimalTestDrive { public static void main (String [] args) { MyAnimalList list = newMyAnimalList(); Dog a = new Dog(); Cat c = new Cat(); list.add(a); list.add(c); } } MyAnimalList Animal[] animals Intnextindex add(Animal a) Animal added at 0 Animal added at 1 Head First JAVA
Object (1/5) 자바에서 모든 클래스는 Object라는 클래스를 확장한 것이다. ArrayList boolean remove(Objectelem) :인자로 주어진 객체를 삭제. Elem 객체가 목록에 있었다면 true 리턴 boolean contains(Objectelem) : 인자로 주어진 객체하고 매치되는 것이 있으면 true 리턴 booleanisEmpty() : 목록에아무 원소도 들어있지 않으면 true 리턴 intindexOf(Objectelem) : 인자로 주어진 인덱스 위치에 있는 원소를 리턴 boolean add(Objectelem) : 인자로 주어진 객체를 목록에 추가 // 기타 메소드.. Head First JAVA
Object (2/5) equals(Object to) Dog a = new Dog(); Cat c = new Cat(); if (a.equals(c)) { System.out.println(“true”); } else { System.out.println(“false”); } 같은지… Object booleanequals() Class getClass() InthashCode() String toString() 그 객체의 클래스 getClass() Cat c = new Cat(); System.out.println(c.getClass()); false class Cat toString() hashCode() Cat c = new Cat(); System.out.println(c.toString()); Cat c = new Cat(); System.out.println(c.hashCode()); Cat@7d277f 8202111 클래스명과 String메시지 객체에 해당하는 해시코드 Head First JAVA
Object (3/5) ArrayList<Dog>myDogArrayLest = new ArrayList<Dog>(); Dog aDog = new Dog(); myDogArrayList.add(aDog); Dog d = myDogArrayList.get(0); 목록에 있는 Dog를 Dog 레퍼런스에 대입 ArrayList<Object>myDogArrayLest = new ArrayList<Object>(); Dog aDog = new Dog(); myDogArrayList.add(aDog); Dog d = myDogArrayList.get(0); Object를 Dog에. ‘불가능’ Object의 하위클래스일 뿐 ArrayList<Object>에서 나오는 객체는 레퍼런스 무조건 Object 유형의 레퍼런스로 나옴. 컴파일러에서는 그 객체가 Object가 아닌 다른 클래스의 인스턴스라 가정할 수 없음. Head First JAVA
Object (4/5) ArrayList로부터 객체레퍼런스를 받아오면 Dog에 대한 Object 레퍼런스를 가짐 Object Dog 객체 Object o = a1.get(index); inti = o.hashCode(); o.bark(); Object 클래스에도 hashCode() 메소드는 있기 때문에 어떤 자바 객체에서도 호출 가능 Object 클래스에서는 bark()의 의미를 알 수 없음 인덱스에 Dog 객체가 들어있다는 것을 컴파일러는 모름 O 컴파일러에서 어떤 메소드를 호출할 수 있는지 결정할 때는 실제 객체 유형이 아닌 레퍼런스 유형을 기준으로 따짐 Head First JAVA
Object (5/5) Snowboard s = new Snowboard(); Object o = s; shred() turn() toString() hashCode() Object equals() getClass() getAir() loseControl() O S Snowboard Snowboard 객체 Head First JAVA
객체 캐스트 Object o = a1.get(index); Dog d = (Dog) o; d.roam(); Dog 객체 객체가 확실히 Dog 객체라면 레퍼런스를 복사한 다음 그 사본을 강제로 Dog 레퍼런스로 O S if (o instanceof Dog) { Dog d = (Dog) o; Dog인지 잘 모르겠다면 instanceof연산자를 사용하여 확인. 엉뚱한 클래스로 캐스트하면 ClassCastException으로 프로그램 정지 Head First JAVA
클래스 트리 수정 (1/3) PetShop프로그램에서 기존 클래스를 재사용하기 위한 방법 애완동물의 성질을 나타내기 위한 메소드를Animal 클래스에… - 모든 Animal 객체가 바로 애완동물의 성질을 상속 가능. - 애완동물이 아닌 동물에 애완동물 메소드를 부여. 동물 별로 애완동물로써의 행동이 달라 따로 수정해야 함. Animal Feline Canine Hippo Lion Tiger Dog Cat Wolf Head First JAVA
클래스 트리 수정 (2/3) Animal 첫 번째 옵션과 같지만 메소드를추상메소드로 만들어서 Animal 하위 클래스에서 오버라이드… - 애완동물이 아닌 클래스에서 애완동물 메소드를 사용할 수 있다는 단점 극복 - 하위클래스 중 구상 클래스에서는 반드시 모든 애완동물 메소드를 구현해야 함 Feline Canine Hippo Lion Tiger Dog Cat Wolf Head First JAVA
클래스 트리 수정 (3/3) Animal 애완동물 메소드는 그 메소드를 사용할 클래스에만… - 메소드가 필요한 클래스에만 들어감. - 애완동물용 메소드에 대해서 다형성을 적용할 수 없음. 모든 애완동물에 있어야만 하는 정확한 메소드(규약)를 모든 프로그래머가 알고 있어야 함. Feline Canine Hippo Lion Tiger Dog Cat Wolf Head First JAVA
다중속성 Pet Animal 애완동물 메소드를Pet 클래스에… - 모든 애완동물 클래스에 똑같은 메소드가 정의되게 함. - 다형성을 활용하여 애완동물용 메소드를 호출할 수 있음. Feline Canine Hippo Cat JAVA에서는 다중속성을 사용할 수 없음 Tiger Dog 죽음의 다이아몬드를 허용하지 않기 때문 Lion Wolf Head First JAVA
인터페이스 public interfacePet { public abstract void beFriendly(); public abstract void play(); } public class Dog extends Canine implements Pet { public void beFriendly() { … } public void play() { … } public void roam() { … } public void eat() { … } } Pet abstract void beFriendly(); Abstract void play(); 자바 인터페이스는 추상 클래스와 비슷 - 모든 메소드가 추상 메소드 - 모든 애완동물 클래스는 Pet의 메소드를 구현(오버라이드) 해야 함 Head First JAVA
인터페이스 다형성 Robot Pet Animal Tiger RoboDog Feline Canine - 서로 다른 상속 트리에 속한 클래스에서도 같은 인터페이스를 구현할 수 있음 - 한 클래스에서 인터페이스 여러 개를구현할 수 있음 Cat Hippo Tiger Dog Lion Wolf Head First JAVA
Super 키워드 abstract class Report { voidrunReport() { // 보고서 설정 } voidprintReoprt() { //포괄적인 인쇄 작업 } } classBuzzwordsReportextends Report { voidrunReport() { super.runReport(); buzzWordCompliance(); printReport(); } void buzzwordCompliance() { … } } 상위클래스 메소드에서 하위클래스에서 사용할 수 있는 작업 처리 상위클래스 버전을 호출한 다음 하위클래스에서 해야 할 일을 처리 Head First JAVA
핵심정리 (1/3) 클래스를 만들 때 인스턴스를 만들 수 없게 하고 싶다면 abstract 키워드를 사용하면 된다. 추상 클래스에는 추상 메소드와 아닌 것을 모두 넣을 수 있다. 클래스에 추상 메소드가 하나라도 있으면 추상 클래스이다. 추상 메소드에는 본체가 없어 세미콜론으로 끝난다. 상속 트리에서 처음으로 나오는 구상 클래스에서는 반드시 모든 추상 메소드를 구현해야 한다. 자바에 들어 있는 모든 클래스는 Object의 하위클래스이다. Head First JAVA
핵심정리 (2/3) 메소드를 선언할 때 인자, 리턴 유형을 Object로 지정해도 된다. 메소드를 호출하려면 레퍼런스가 참조하는 객체의 유형과는 무관하게 레퍼런스 변수유형의 클래스에 그 메소드가 있어야 한다. Object 유형의 레퍼런스 변수는 캐스팅을 하지 않고는 다른 유형의 레퍼런스에 대입할 수 없다. ArrayList<Object>에서 나오는 것은 Object 유형으로 나온다. 자바에서는 다중 상속을 허용하지 않는다. 인터페이스는 100% 순수한 추상 클래스이다. 추상 메소드만 정의 Head First JAVA
핵심정리 (3/3) 인터페이스를 만들 때는 class 대신 interface 키워드를 사용한다. 인터페이스를 구현할 때는 implements라는 키워드를 사용한다. 클래스를 만들 때 인터페이스를 여러 개 구현할 수 있다. 인터페이스를 구현하는 클래스에서는 인터페이스에 들어있는 모든 메소드를 구현해야 한다. 하위클래스에서 어떤 메소드를오버라이드 했는데, 상위클래스 버전을 호출하고 싶다면 super라는 키워드를 사용한다. Head First JAVA