국비/Java

[12-1] Java 다형성 Polymorphism, 추상클래스, 추상메소드, 인터페이스

제발 취업하게 해주세요 2022. 4. 22. 23:19
추상클래스
[표현법]
접근제한자 abstract class 클래스이름{}
  public     abstract   class  Sports    {
               abstract : 예약어 -> 추상클래스, 추상메소드 선언할 때 붙인다

 * 추상메소드가 존재하는 순간 추상클래스로 정의
 * abstract라는 예약어를 사용해서 정의해야 한다
 * 객체 생성이 불가능하다, .부모클래스 구실은 가능 (다형성 적용)
   => 클래스가 미완성이기 때문에
 * 추상클래스 == 일반필드 + 일반메소드 + 추상메소드(생략가능)
   => 추상메소드가 없어도 추상클래스로 정의 가능

Sports s = new Sports();  --> X 객체 생성 불가
Sports s; ---> 객체생성 x 참조형 변수로 사용 o
Sports s1 = new Soccer(); ---> 다형성을 이용하여 자식객체를 받아주는 용도로 사용 가능.



 * 언제?? 개발자의 역량
 * => 기술적으로 개발자가 판단했을 때 이 클래스는 객체 생성이 불가능해야한다 라고 생각이들면 추상클래스로 가능
 * => 개념적으로 개발자가 판단했을 때 해당 클래스 가 아직 구체적으로 덜 구현된 상태인 것 같다.
추상메소드
[표현법]
 접근제한자 abstract 반환형 메소드이름(){
  public      abstract  void       rule      ();

 * method body {   } 가 존재하지 않는 미완성메소드
 * 반드시 abstract 예약어를 써서 정의해야 한다.

 * 미완성 메소드가 하나라도 포함되는 순간 해당 클래스는 미완성클래스(추상클래스)가 됨
 * 해당 클래스 앞에도 abstract라는 예약어를 써야한다.
 * 추상메소드가 있으면 해당 클래스도 추상클래스가 된다!!!


장점
 * 메소드 사용의 통일성 확보
 * 표준화된 틀 제공 => 상속받는 자식클래스의 경우 반드시 미완성메소드를 완성시켜야 함
 ---> 추상클래스를 상속받으면 미완성된 메소드를 재정의해서 완성시키거나
 ---> 자식클래스도 abstract클래스로 만들어주거나
인터페이스
자바에서의 인터페이스

 * [표현법]

  접근제한자 interface 인터페이스이름{
       상수필드(static final
       추상메소드
       }

상수필드, 추상메소드 딱 두 가지만 들어갈 수 있다!!!!

  - 상수필드와 추상메소드만으로 이루어진 추상 클래스의 변형체
  - 인터페이스 필드는 "무조건" 상수필드
  - 인터페이스에서 메소드는 "무조건" 추상메소드
   
  - 인터페이스는 다중상속을 허용한다.
      => 왜? 메소드가 겹치더라도 최종 구현 부분은 구현 클래스에서 기술하기 때문
   
  - 무조건 구현해야 하는 게 있을 때 인터페이스 틀만 만들어두고 상속하게 => 오버라이딩!!
   
   추상클래스와 인터페이스
   1. 공통점
     - 객체 생성은 안되나, 참조변수로 사용이 가능하다(다형성을 적용할 수 있다)
     - 상속하는 클래스에서 추상메소드를 오버라이딩하도록 강제한다.
   2. 차이점
     - 추상클래스 : 클래스 멤버로, 일반필드, 일반메소드 생성이 가능하고
       추상 메소드가 포함되어 있거나 abstract 키워드를 통해 정의됨
     - 이너페이스 : 모든 필드는 상수 필드, 모든 메소드가 추상메소드로 정의해야 함
   
     => 존재하는 목적이 다름!
 
    추상클래스는 추상클래스를 상속받아서 기능을 이용하고 클래스를 확장하기 위한 용도 
    인터페이스는 클래스의 기능(메소드) 구현을 강제하기 위해서 사용!!
 
    extends(확장)와 implements(구현)

  - 클래스간의 상속 관계 : 자식클래스 extends 부모클래스
  - 클래스와 인터페이스 구현 관계 : 클래스 Implement 인터페이스
  - 인터페이스간의 상속 관계 : 자식인터페이스 extends 부모인터페이스1, 부모인터페이스2 >> 이렇게 쓰는 경우 거의 x
  
public interface Basic {
	
	// 인터페이스에서는 무조건 상수필드와 추상메소드밖에 정의가 불가하므로
	// 접근제한자, 예약어 생략 가능
	
	// 상수필드
	/*public static final*/ int NUM = 10;	
	// 추상메소드
	/*public abstract*/ void eat();
    
    // 인터페이스의 모든 필드들은 암묵적으로 public, static final이다.
	// 인터페이스의 모든 메소드들은 암묵적으로 public abstract이다.
    }
Person : 부모클래스, 추상 메소드를 가진 추상 클래스
public abstract class Person {

	private String name;
	private double height;
	private double weight;
	
	public Person() {}
	
	public Person(String name, double height, double weight) {
		super();
		this.name = name;
		this.height = height;
		this.weight = weight;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getHeight() {
		return height;
	}
	public void setHeight(double height) {
		this.height = height;
	}
	public double getWeight() {
		return weight;
	}
	public void setWeight(double weight) {
		this.weight = weight;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", height=" + height + ", weight=" + weight + "]";
	}
	
	public abstract void eat(); 
	public abstract void sleep(); 
	// 추상메소드
	
}
Mother - Person의 자식클래스
public class Mother extends Person{

	private String babyBirth;
	
	public Mother() {}

	public Mother(String name, double height, double weight, String babyBirth) {
		super(name, height, weight);
		this.babyBirth = babyBirth;
	}

	public String getBabyBirth() {
		return babyBirth;
	}
	public void setBabyBirth(String babyBirth) {
		this.babyBirth = babyBirth;
	}
	@Override
	public String toString() {
		return super.toString() + "babyBirth=" + babyBirth;
	}
	@Override
	public void eat() { 
		super.setWeight(super.getWeight() + 3);
	}
	@Override
	public void sleep() {
		// 키 0.1 증가
		super.setHeight(super.getHeight() + 0.1);	
	}​
Person의 자식클래스, 인터페이스
public class Baby extends Person implements Basic{

	
	public Baby() {}
	public Baby(String name, double height, double weight) {
		super(name, height, weight);
	}

	@Override
	public String toString() {
		return super.toString();
	}
	
	@Override
	public void eat() { // 애기가 밥 먹을 때는?
		// 몸무게 0.5 증가
		// weight == 부모의 필드 + 0.5
		// 수정할 몸무게 == 기존의 몸무게
		super.setWeight(super.getWeight() + 0.5);
	}

	@Override
	public void sleep() {
		// 키 0.5 증가
		super.setHeight(super.getHeight() + 0.5);	
	}
}
Run - 실행클래스
public class Run {

	public static void main(String[] args) {

	//	Person p = new Person();
		// 추상클래스, 객체 생성 불가

	/* 다형성 적용 인터페이스 적용 전
		Person mom = new Mother("엄마", 170, 70, "출산");
		Person baby = new Baby("아가", 34, 2.5);
		
		System.out.println(mom);
		System.out.println(baby);
		
		mom.eat();
		baby.eat();
		mom.sleep();
		baby.sleep();
		
		System.out.println("----------------다음날-------------");
		System.out.println(mom);
		System.out.println(baby);
	}*/

	// 인터페이스 적용 후
		Person mom = new Mother("엄마", 170, 70, "출산");
		Person baby = new Baby("아가", 34, 2.5);
		
		System.out.println(mom);
		System.out.println(baby);
		
		mom.eat();
		baby.eat();
		mom.sleep();
		baby.sleep();
		
		System.out.println("-------------다음날-------------");
		System.out.println(mom);
		System.out.println(baby);
		}
}
다형성 적용, 인터페이스 적용 전

다형성, 인터페이스 적용 후