Java

Java 문법(9) - 상속, 추상화

sangchu 2022. 2. 8. 12:41

상속, 부모클래스와 자식클래스

  • 상속: 클래스의 멤버를 물려준다
  • 부모 클래스: 물려주는 클래스
  • 자식 클래스: 물려받는 클래스
public class Main {

	public static void main(String[] args) {
		Parent p = new Parent();
		Child c = new Child();
		
		p.print();
		c.print();
	}

}

// Parent 클래스 정의
class Parent {
		
	public int iInt;
	
	public void print() {
		System.out.println("Parent Class");
	}
}

// Child 클래스 정의
class Child extends Parent{

}

// > Parent Class
//   Parent Class
  1. 14~21번째 줄: Parent라는 클래스 정의. 클래스 멤버는 iInt라는 변수와 print라는 메소드로 구성
  2. 23~26번째 줄: Child라는 클래스 정의. extends 구문을 통해 상속을 나타냄
    • 클래스를 정의할 때 클래스 이름 옆에 extends 구문을 붙여준 후 부모 클래스 이름을 적어주면 자식 클래스는 부모 클래스를 상속하게 됨
    • 자식 클래스는 부모 클래스의 private 멤버를 제외한 나머지 멤버를 본인의 멤버처럼 사용 가능
    • 위 예제에서 Child 클래스 내부에 아무것도 적지 않았지만 상속받았으므로 iInt변수와 print() 메소드를 Child 클래스의 멤버로 사용할 수 있음
  3. main함수를 보면, Child 클래스의 객체 c에서 print 메소드를 사용한걸 확인 할 수 있음 → Child 클래스에도 print 메소드가 정의되어 있으며 사용까지 가능하다
  • 상속
    • 자식 클래스는 부모 클래스로부터 물려받은 멤버 외에 다른 멤버를 추가로 가질 수 있음
    • 자식 클래스에서 정의된 멤버는 부모클래스 객체에서는 사용할 수 없음
    • 자식 클래스 객체가 생성될 때는 부모클래스의 생성자가 무조건 콜 됨 콜 순서는 부모클래스 생성자, 자식클래스 생성자 순

 

접근제한자: protected

  • 부모 클래스에서 protected로 선언된 멤버는 자식 클래스에서 상속 받아 public처럼 사용할 수 있음.
  • 단, 본인 클래스 혹은 자식 클래스 외의 장소에서 사용할 경우 해당 멤버는 private과 동일하게 동작함
  • 부모 클래스에서 private로 선언된 멤버는 자식 클래스에서도 사용 불가능

 

오버라이딩(overriding)

  • 부모 클래스의 멤버를 자식 클래스에서 재정의하여 사용하는 것
public class Main {

	public static void main(String[] args) {
		Parent p = new Parent();
		Child c = new Child();
		
		p.print();
		c.print();
	}

}

// 부모 클래스 정의
class Parent {
		
	public int iInt;
	
	public void print() {
		System.out.println("Parent Class");
	}
}

// 자식 클래스 정의
class Child extends Parent{

	public void print() {
		System.out.println("Child Class");
	}
}
  • 앞서 다룬 예제에서는 Child 클래스에 어떤 내용도 존재하지 않았음. 위 코드에스는 print 메소드를 정의함
    • 자식 클래스에서 부모 클래스에 정의된 메소드를 재정의함
    • 부모 클래스의 멤버를 상속 받았지만, 자식 클래스에서 해당 멤버의 내용을 수정했으므로 자식 클래스 객체에서는 바뀐 내용이 적용됨
    • 부모 클래스에는 영향x

 

추상화 & 추상클래스

  • 추상화는 상속에서만 사용될 수 있는 개념
  • 부모 클래스에서 추상적으로 메소드를 만들어 놓으면, 자식 클래스에서 해당 메소드를 구체화 함
public class Main {
	public static void main(String[] args) {
		
		//Animal animal = new Animal("동물"); 불가능합니다.
		
		Lion lion = new Lion("사자");
		lion.Growl();
		
		Cat cat = new Cat("고양이");
		cat.Growl();
	}
}

abstract class Animal {
	
	String Name;
	
	public Animal(String name) {
		Name = name;
	}
	
	abstract public void Growl(); 
}

class Lion extends Animal {

	public Lion(String name) {
		super(name);
	}

	public void Growl() {		
		System.out.println("어흥");
	}
}

class Cat extends Animal {
	public Cat(String name) {
		super(name);
	}
	
	public void Growl() {		
		System.out.println("야옹");
	}
}
  1. Animal 클래스는 생성자와 Growl 메소드를 가진 클래스인데, Growl 메소드에 abstract 라는 문구가 붙음
    • abstract 가 명시된 메소드를 추상화 메소드라하며, 추상화 메소드는 내용을 정의하지 않음 → 껍데기만 존재하는 메소드, 상속된 후 자식 클래스에서 정의하여 사용 가능
  2. 추상화 메소드를 가진 클래스를 추상 클래스라 함. 추상 클래스에도 abstract 를 명시해야 함. 추상 클래스는 객체화 할 수 없음
  3. 부모 클래스에서 Growl 메소드를 정의하지 않았으므로, 자식클래스에서 오버라이딩해야함 → 오버라이딩 안하면 자식 클래스도 abstract 클래스가 됨
  4. 28번째 줄, 38번째 줄: super 는 부모 클래스를 지칭하는 문구. 위 예제에서는 super(name)이 Animai(name)과 동일
  • 부모 클래스에서 추상화를 통해 클래스 구조의 뼈대만 구성해두고 자식 클래스에서 목적에 맞게 오버라이딩하여 사용 → 좀 더 구조화된 프로그램을 만들 수 있음

 

interface

  • Java에서는 다른 프로그래밍 언어에서 사용할 수 있는 다중 상속 기능을 제한함 ⇒ extends 뒤에 작성할 수 있는 클래스는 단 하나
  • 하지만 상황에 따라 다중 상속이 필요함 ⇒ interface 기능
  • interface: 추상화 클래스보다 좀 더 추상화된 클래스
interface Example {
	public static final int iVariable;
	// int iVariable만 써도 동일함.
	
	abstract public void method();
	// void method()만 써도 동일함.
}
  • class와 비슷한데 class 대신 interface라는 구문을 사용하며, 멤버 변수는 public static final 형태만 사용할 수 있고, 메소드도 abstract public 형태만 가능
  • public static final과 abstract public은 interface 내에서 생략 가능
  • 알맹이 하나 없이 뼈대만 세워진 클래스
public class Main {
	public static void main(String[] args) {
		MP3Player_Ver1 mp3_ver1 = new MP3Player_Ver1();
		mp3_ver1.Play();
		mp3_ver1.Stop();
		//mp3_ver2.Next(); 불가능 합니다.
		//mp3_ver2.Prev(); 불가능 합니다.
		
		MP3Player_Ver2 mp3_ver2 = new MP3Player_Ver2();
		mp3_ver2.Play();
		mp3_ver2.Stop();
		mp3_ver2.Next();
		mp3_ver2.Prev();
	}
}

class MP3Player_Ver1 implements PlayFunction, StopFunction {
	public void Play() {
		System.out.println("Play_Ver1!");
	}

	public void Stop() {
		System.out.println("Stop_Ver1!");
	}
}

class MP3Player_Ver2 implements PlayFunction, StopFunction, NextFunction, PrevFunction {
	public void Play() {
		System.out.println("Play_Ver2!");
	}

	public void Stop() {
		System.out.println("Stop!_Ver2");
	}
	
	public void Next() {
		System.out.println("Next!_Ver2");
	}
	
	public void Prev() {
		System.out.println("Prev!_Ver2");
	}
}

interface PlayFunction {
	abstract public void Play();
}

interface StopFunction {
	abstract public void Stop();	
}

interface NextFunction {
	abstract public void Next();
}

interface PrevFunction {
	abstract public void Prev();
}
  • interface로부터 상속받을 시, extends를 사용하지 않고 implements를 사용함
  1. MP3Player_Ver1 클래스는 PlayFunction과 StopFunction, 총 두 개의 interface를 상속 받음. interface에 정의된 메소드는 모두 abstract형이므로, 17~25번째 줄에서 두 메소드를 모두 오버라이딩 함
  2. main 함수 내에서 MP3Player_Ver1 및 MP3Player_Ver2 사용 시, MP3Player_Ver1의 객체에서는 Next와 Prev 메소드는 정의되지 않으므로 사용 불가능

추상 클래스는 일부 멤버만 추상화할 수 있지만 1개의 클래스만 상속할 수 있고, interface는 모든 멤버 메소드가 추상 메소드여야 하지만 여러 개를 동시에 상속할 수 있음상속, 부모클래스와 자식클래스

 
 
 
 
 
 
 

바로 실행해보면서 배우는 java'를 학습하며 정리한 문서