java.lang.Object
extends
가 없는 클래스) 모두 Object 클래스의 서브 클래스이다.public static void main(String[] args) { Object obj = new Person(); ((Person)obj).setName("홍길동"); ((Person)obj).setAge(20); System.out.println(((Person)obj).getName()); System.out.println(((Person)obj).getAge()); }
추상 : 정확하게 갖춰진 형태가 없는 것
abstract
키워드를 추가한다.abstract
키워드를 추가하고 본문({}
)을 제거한다.JDK 1.7 이전에는 추상 메소드 + final 상수로만 구성된 추상 클래스를 의미했다.
JDK 1.8 이후로는 추상 메소드 + default 메소드 + static 메소드 + final 상수로 구성된다.
인터페이스의 추상 메소드는 public abstract
를 생략할 수 있다.
인터페이스를 구현한 클래스는 반드시 추상 메소드를 오버라이드 해야 한다.
extends
Person { }implements
Shape { }public static void ex01() { // Object 타입으로 모든 객체를 저장할 수 있다. // Object 타입으로 저장한 객체를 사용할 때는 캐스팅 해야 한다. Object obj = new Person(); ((Person)obj).setName("홍길동"); ((Person)obj).setAge(20); System.out.println(((Person)obj).getName()); System.out.println(((Person)obj).getAge()); }
public static void ex02() { // 동일한 객체 2개 Person p1 = new Person("홍길동", 20); Person p2 = new Person("홍길동", 20); // 동일한 객체인지 판단 boolean same = p1.equals(p2); // Person클래스에서 override 하지 않으면 두 객체의 참조값 비교만 됨. // 결과 확인 System.out.println(same ? "동일한 객체" : "다른 객체"); }
public static void ex03() { Person p = new Person("홍길동", 20); // Person에서 toString 오버라이드를 해서 객체의 값을 반환 System.out.println(p); // 객체 p는 p.toString()이 자동 호출돼서 사용된다. // System.out.println(p.toString()); }
public static void main(String[] args) { ex01(); ex02(); ex03(); }
public class Person { private String name; private int age; // new Person() public Person() { } // new Person("홍길동", 20) public Person(String name, int age) { this.name = name; this.age = age; } // 오브젝트의 메소드를 오버라이드 @Override public int hashCode() { return Objects.hash(age, name); } @Override public boolean equals(Object obj) { if (this == obj) // p1.equals(p1) return true; if (obj == null) // p1.equals(null) return false; if (getClass() != obj.getClass()) // p1.equals(s1) 다른 클래스 비교 == false return false; Person other = (Person) obj; // 캐스팅 return age == other.age && Objects.equals(name, other.name); // 내용비교 } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; // 이름과 나이의 문자열 반환 } // Getter & Setter public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
실행 클래스
public static void main(String[] args) { // 추상 클래스 Person은 객체를 생성할 수 없다. // Person p1 = new Person(); // p1.eat(); // p1.sleep(); Person p2 = new Student(); p2.eat(); // 냠냠 출력 p2.sleep(); // 쿨쿨 출력 p2.study(); // 공부 출력 }
추상 클래스 (Person)
public abstract class Person { public void eat() { System.out.println("냠냠"); } public void sleep() { System.out.println("쿨쿨"); } // 추상 메소드 // 호출을 위해서 생성한 study public abstract void study(); }
Person 클래스를 상속하는 Student 클래스
public class Student extends Person{ @Override public void study() { System.out.println("공부"); } }
실행 클래스
public class MainWrapper { public static void main(String[] args) { Phone p = new SmartPhone(); p.call(); p.sms(); if(p instanceof Computer) { ((Computer) p).game(); ((Computer) p).internet(); } if(p instanceof Camera) { ((Camera) p).takePictuer(); } Computer c = new SmartPhone(); c.game(); c.internet(); if(c instanceof Phone) { ((Phone) c).call(); ((Phone) c).sms(); } if(c instanceof Camera) { ((Camera) c).takePictuer(); } SmartPhone sp = new SmartPhone(); sp.call(); sp.sms(); sp.game(); sp.internet(); sp.takePictuer(); } }
스마트폰 클래스
public class SmartPhone extends Camera implements Phone, Computer { @Override public void game() { System.out.println("게임"); } @Override public void internet() { System.out.println("인터넷"); } @Override public void call() { System.out.println("전화"); } @Override public void sms() { System.out.println("문자"); }
Phone 인터페이스
public interface Phone { void call(); void sms(); }
Computer 인터페이스
public interface Computer { void game(); void internet(); }
Camera 클래스
public class Camera { public void takePictuer() { System.out.println("사진찍기"); } }
실행 클래스
public static void main(String[] args) { Person p = new Person(); p.eatEverything(new AppleMango("애플망고")); // 애플망고 먹는다. p.eatEverything(new Coriander("고수")); // 고수 먹는다. p.eatPossible(new AppleMango("애플망고")); // 애플망고 먹는다. -- 타입체크 // p.eatPossible(new Coriander("고수")); // 컴파일 오류 발생 -- 타입체크 }
실행결과
Food 클래스
public class Food { private String name; public Food(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } // 참조값이 아닌 객체에 들어있는 데이터를 확인하기 위해 오버라이드 @Override public String toString() { return "Food [name=" + name + "]"; } }
Eatable 인터페이스
public interface Eatable { //인터페이스 타입체크 : 주로 이름에 able이 붙음. }
AppleMango 클래스
public class AppleMango extends Food implements Eatable { public AppleMango(String name) { super(name); // 슈퍼 클래스의 public Food(String name) { } 생성자 호출 } }
Coriander 클래스
public class Coriander extends Food { public Coriander(String name) { super(name); } }
Person 클래스
public class Person { public void eatEverything(Food food) { System.out.println(food + " 먹는다."); } public void eatPossible(Eatable food) { // 타입체크 System.out.println(food + " 먹는다."); } }
😎사실 저는 고수 잘 먹습니다. 👍