[JAVA] 상속(Object 클래스) - 추상 / 인터페이스

Gabriela·2023년 7월 26일
0

JAVA

목록 보기
13/24
post-thumbnail

‣ Object 클래스

java.lang.Object

  • 모든 클래스의 최상위 슈퍼 클래스
  • 별도의 슈퍼 클래스를 명시하지 않은 클래스들은(extends가 없는 클래스) 모두 Object 클래스의 서브 클래스이다.
  • 모든 것을 저장할 수 있는 Java의 만능 타입이다.
  • Object 타입으로 저장하면 Object 클래스의 메소드만 호출할 수 있다. 이를 해결하기 위해서 반드시 캐스팅을 해야 한다.

• 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());
  }

• Object 클래스 상속 관계 도식화


‣ 추상 클래스

추상 : 정확하게 갖춰진 형태가 없는 것


  • 추상 메소드를 1개 이상 가지고 있는 클래스이다.
  • abstract 키워드를 추가한다.
  • 추상 클래스는 객체를 생성할 수 없다. (미완성 된 클래스이기 때문이다.)
  • 추상 클래스의 서브 클래스는 반드시 추상 메소드를 오버라이드 해야 한다.

‣ 추상 메소드

  • 본문이 필요 없기 때문에 본문이 없는 메소드로 만들 수 있다.
  • 본문이 없는 메소드를 추상 메소드라고 한다.
  • abstract 키워드를 추가하고 본문({})을 제거한다.

‣ 인터페이스

interface


  • JDK 1.7 이전에는 추상 메소드 + final 상수로만 구성된 추상 클래스를 의미했다.

  • JDK 1.8 이후로는 추상 메소드 + default 메소드 + static 메소드 + final 상수로 구성된다.

    1. 추상 메소드 : 본문이 없는 메소드 (대부분은 추상 메소드로 구성됨)
    2. default 메소드 : 본문이 있는 메소드
    3. static 메소드 : 클래스 메소드 (본문 있음)
  • 인터페이스의 추상 메소드는 public abstract를 생략할 수 있다.

  • 인터페이스를 구현한 클래스는 반드시 추상 메소드를 오버라이드 해야 한다.


  • 인터페이스는 다중 구현이 가능하다.
  • 클래스 상속과 인터페이스 구현을 동시에 할 수 있다.(상속 먼저, 구현 나중)

클래스 상속 & 인터페이스 구현 비교

  1. 클래스를 상속 받는다.

    public class Person { }
    public class Student extends Person { }
  1. 인터페이스를 구현한다.

    public interface Shape { }
    public class Rectangle implements Shape { }

인터페이스 구현체 생성

  • 우클릭 - New - interface - add - (최초 1번은 검색을 해서 찾아야 한다.)


‣‣ Object 클래스 Override 활용 예제

실행 클래스

  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();
  }

Person 클래스

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 + " 먹는다.");
  }
}

😎사실 저는 고수 잘 먹습니다. 👍

profile
개발이 세상에서 제일 재밌어요

0개의 댓글

관련 채용 정보