추상 클래스

zee-chive·2024년 7월 22일

Java

목록 보기
6/12

다형성

  • 실제 하나의 객체를 다양한 타입의 참조로 사용하는 것
  • 다양한 유형의 여러 객체를, 하나의 공통된 타입으로 참조
  • 상속 관계에 있을 때, 조상 클래스 타입으로 자손 클래스 객체 참조 가능
    • 다양한 타입으로 참조하더라도, 참조만 바뀌며, 실제 객체 자체는 변함 없음
  • 하나의 이름으로 다양한 기능 구현 가능


  • 다형성 종류
    • 임시 다형성 : 메서도 오버로딩, 연산자 오버로딩(같은 연산자를 여러 기능 갖도록, 자바에서 지원하지 않음)
    • 매개변수 다형성 : 재너릭
    • 서브타입 다형성 : 상속 관계에 있을 때 조상 클래스 타입으로 자손 객체 참조 가능
  • 다형성 장점
    • 코드 재사용성 증가
    • 유연성과 확장성 증가
    • 가독성 개선

public class Test {
    public static void main(String[] args) {
        // 다형성 
        // 1. 상속 관계에 있을 때, 조상 클래스 타입으로 자손 클래스 객체 참조 가능 

        Student st = new Student();

        Person p = new Student();

        Object obj = new Student();
    }
}
  1. 부모 클래스 타입으로 참조를 바꾼다면, 부모 클래스에 정의된 메서드, 변수만 접근 가능.
  2. 동적 바인딩 : 상속을 하면서 자손 클래스에서 오버라이드하는 경우
    • 타입과 관계 없이, 실제 객체가 가진 메서드가 호출된다.
    • 학생을 사람이라는 박스에 넣더라도, 여전히 학생이다.
      (p의 경우, Person 박스에 있더라도, 여전히 Student에 들어가 있는다.

    • 동적 바인딩 : 상속 + 오버라이드 ( 상속 관계에 있을 때, 자식 클래스가 부모 클래스의 메서드 재정의)
    • 멤버 메서드에는 다형성이 적용되지만, 멤버 변수에는 다형성이 적용되지 않는다.
    • static method 에는 다형성이 적용되지 않는다.
      - static method 는 어차피 클래스의 것이므로, Parent.Static_method 와 같이 작성해야 한다.
package test03_binding_test;


class Parent {
    String x = "parent x";
    
    public void method() {
        System.out.println("parent method.");
    }
    
    public static void static_method() {
		System.out.println("parent static method.");
	}
}

class Child extends Parent{
    String x = "child x";
    
    @Override
    public void method() {
        System.out.println("child method.");
    }
    
    public static void static_method() {
		System.out.println("child static method.");
	}
}

public class BindingTest {
    
    public static void main(String[] args) {
    	Parent p = new Child();
    	Child c = new Child();
    	
    	System.out.println(p.x);
    	p.method();
    	p.static_method();
    	System.out.println(c.x);
    	c.method();
    	c.static_method();
    }
}

Console

parent x
child method.
parent static method.
child x
child method.
child static method.





참조 변수의 형 변환

  1. 묵시적 형변환 (조상타입 ← 자손타입) : 형 변환 생략이 가능하다.
    • Student st = new Student(); Person p = st;
  2. 명시적 형변환 (조상타입 → 자손타입) : 형 변환 생략이 불가능하다.
    • 자손 객체를 만든 다음, 부모 클래스로 형변환을 하였다가 다시 돌아오는 경우에만, 에러 발생하지 않는다.
    • 객체를 바로 조상 클래스에 넣는 경우에는 불가능
	Person p = new Student();
	Student st = (Student) p;
    
    //Student st = (Student) new Person(); → ClassCastException




instanceof 연산자 (객체 instanceof 클래스이름)

  • 참조 변수가 참조하고 있는 인스턴스의 타입을 확인하기 위해서 사용.
  • 결과를 boolean으로 반환
  • 해당 클래스로 묵시적 형변환이 가능하다면 true, 아니라면 false
    	Person[] persons = new Person[3];
    	
    	persons[0] = new Person("park", 27);
    	persons[1] = new Student("Kim", 22, "Java");
    	persons[2] = new Student("Lee", 22, "Java");
    	
    	for(Person person : persons) {
    		System.out.println(person);
    		person.eat();
    		
    		// 만약 Student 객체만 출력하고 싶은 경우, 
    		if (person instanceof Student) {
    			System.out.println(person);
    		}
    	}





추상 클래스 (abstract class)

  • 코드를 줄일 때 사용되지 않는 부모의 메소드를 삭제하게 되는 경우가 있다.
    • 이런 경우 자식에서 오버라이드 중인 메소드를 삭제하면 오류 발생
    • 참조형 변수에서 참조 불가능한 일이 생긴다.
  • 추상 메서드를 만들어서 변경 가능 : 추상 메서드는 ; 으로 종료되어야 한다.
  • 추상 메서드를 하나라도 갖고 있다면, 해당 클래스는 추상 클래스가 되어야 한다.
  • 추상 클래스로는 객체 생성 불가능하다.
package test06;
abstract class Animal {
    private String name;
    private int age;

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

//    public void speak() {
//        System.out.println("동물이 소리를 냅니다");
//    }
    public abstract void speak();
  • Animal 의 타입으로 참조하였을 때, 해당 메서드가 목록에서 보이지만,
    실행될 때는 자식 클래스에서 오버라이드한 메서드가 실행.

  • Animal[] animals = new Animal[3]; 과 같이 생성하게 되는 경우, 객체 생성이 아닌 배열 생성이므로 가능하다.

  • 추상 메서드가 없어도, class 에 abstract 선언 가능하다.



추상 클래스의 자식 클래스는
1. 모든 추상 메서드를 오버라이드
2. 오버라이드 하지 않으면, 추상 메서드로 남아야 한다.

추상 클래스는 구현의 강제를 통해 프로그램의 안정성을 향상한다.
1. 객체를 생성하지 말 것이라는 의미
2. 상속과 오버라이딩 사용 후 객체 생성하여 사용하라는 의미를 보이기도 한다.
3. 객체 생성은 일반 class를 통해, 다형성을 유지하라는 의미.



profile
누가 봐도 읽기 쉬운 글이 최고의 글이다.

0개의 댓글