Binary World

JAVA CLASS : 상속(final, abstract) 본문

개발자의 길/JAVA

JAVA CLASS : 상속(final, abstract)

모쿠 2017. 1. 3. 17:42

<final, abstract>


1. final 선언

- final: 최종적인, 변경할 수 없는

- final + 멤버 변수, 지역 변수: 상수(한번 초기화된 값을 변경할 수 없는 변수)

- final + 메소드: override할 수 없는 메소드

- final + 클래스: 상속을 허용하지 않는 클래스


2. abstract 선언

- abstract: 추상적인, 실체가 없는

- abstract 메소드(추상 메소드):

   메소드의 원형(prototype: 리턴 타입, 이름, 매개변수)만 선언하고,

   메소드의 본체(body)를 구현하지 않은 메소드

   {...} 이 없음

   추상 메소드는 반드시 ;으로 끝남

   abstract 리턴타입 메소드이름(매개변수, ...); 형식으로 선언

- abstract 클래스(추상 클래스):

   추상 메소드를 하나라도 가지고 있는 클래스

   abstract class 클래스이름 {...} 형식으로 정의

   추상 클래스는 인스턴스를 생성할 수 없다! (생성자를 호출할 수 없다!)

   상속받는 클래스에서 추상 메소드를 override하면 인스턴스를 생성할 수 있음.


<프로그램 코드>


1. 배열을 이용한 클래스의 다양한 변수출력


* Employee.java (직원 이름 변수, 출력 메소드 선언, 부모 클래스)


package edu.java.inherit08;


public class Employee {

private String name;

public Employee(){}

public Employee(String name){

this.name = name;

}

public String getName(){

return name;

}

public void test() {

System.out.println("직원");

}


}



* Manager.java (직급 변수, 출력 메소드 선언, 자식 클래스)


package edu.java.inherit08;


public class Manager extends Employee{

private String type;

public Manager (String name, String type){

super(name);

this.type = type;

}

public String getType(){

return type;

}

@Override

public void test() {

System.out.println("매니저");

}



* EmpUtil.java (형변환을 통한 출력 메소드를 갖는 클래스)


package edu.java.inherit08;


// 강제 형변환 클래스

public class EmpUtil {

public static void printEmpInfo(Employee emp){

if (emp instanceof Manager) {

Manager m = (Manager) emp;

System.out.println("이름: " + m.getName());

System.out.println("직책: " + m.getType());

} else if ( emp instanceof Employee){

System.out.println("이름: " + emp.getName());

} else {

System.out.println("직원이 아닙니다");

}

}




* InheritMain08.java (메인 클래스)


package edu.java.inherit08;


public class InheritMain08 {


public static void main(String[] args) {

// Employee 클래스 타입의 배열을 선언

Employee[] emps = new Employee[2];

emps[0] = new Employee("홍길동");

emps[1] = new Manager("춘향", "과장"); // 다형성의 장점

for(Employee e : emps){

EmpUtil.printEmpInfo(e);

System.out.println("------------------");

}

emps[0].test();

emps[1].test();

((Manager) emps[1]).test(); // 위의 출력문과 같음


} // end main()


} // end class InheritMain08 



* 출력화면


이름: 홍길동

------------------

이름: 춘향

직책: 과장

------------------

직원

매니저

매니저



2. final을 사용하여 멤버변수, 메소드, 클래스를 변경하지 못하게 선언


* InheritMain11.java


package edu.java.inherit11;


// final: 최종적인, 변경할 수 없는

// final + 멤버 변수, 지역 변수: 상수(한번 초기화된 값을 변경할 수 없는 변수)

// final + 메소드: override할 수 없는 메소드

// final + 클래스: 상속을 허용하지 않는 클래스


class SuperClass {

public void test() {

System.out.println("테스트1");

}

public final void testFinal(){

System.out.println("파이널 메소드");

}

} // end class SuperClass


class SubClass extends SuperClass{

@Override

public void test(){

System.out.println("override된 테스트");

}

// public void testFinal(){

// System.out.println("override 불가능");

// }

} // end class Subclass


final class FinalClass {

private int x;

}


// class ChildClass extends FinalClass {

//

// }

public class InheritMain11 {

public static final int MAX = 100; // final 멤버 변수


public static void main(String[] args) {

// MAX = 200; // 변경 불가

final int number = 123; // final 지역 변수

// number = 1212; // 변경 불가

}



3. abstract 선언 방법 및 출력 화면


* InheritMain11.java


package edu.java.inherit12;


// abstract: 추상적인, 실체가 없는

// abstract 메소드(추상 메소드):

//   메소드의 원형(prototype: 리턴 타입, 이름, 매개변수)만 선언하고,

//   메소드의 본체(body)를 구현하지 않은 메소드

//   {...} 이 없음

//   추상 메소드는 반드시 ;으로 끝남

//   abstract 리턴타입 메소드이름(매개변수, ...); 형식으로 선언

// abstract 클래스(추상 클래스):

//   추상 메소드를 하나라도 가지고 있는 클래스

//   abstract class 클래스이름 {...} 형식으로 정의

//   추상 클래스는 인스턴스를 생성할 수 없다! (생성자를 호출할 수 없다!)

//   상속받는 클래스에서 추상 메소드를 override하면 인스턴스를 생성할 수 있음.


abstract class TestAbstract {

private int x; // 멤버 변수

// 메소드

public int getX(){

return x;

}

public void setX(int x){

this.x = x;

}

// 추상 메소드 : 본체가 없는 메소드

public abstract void hello();

} // end class TestAbstract


class TestChild1 extends TestAbstract {


// 추상 클래스를 상속받는 자식 클래스에서

// 추상 메소드를 override(재정의)해서 본체를 정의

@Override

public void hello() {

System.out.println("안녕하세요~");

}


} // end class TestChild1


class TestChild2 extends TestAbstract {


@Override

public void hello() {

System.out.println("Hello~~");

}

} // end class TestChild2


public class InheritMain12 {


public static void main(String[] args) {

// 추상 클래스는 인스턴스를 생성할 수 없다!

// TestAbstract test1 = new TestAbstract();

// Testchild1 클래스 인스턴스 생성

TestChild1 child1 = new TestChild1();

child1.setX(123);

System.out.println("x = " + child1.getX());

child1.hello();

// 다형성

TestAbstract child2 = new TestChild1();

child2.hello();

System.out.println();

TestChild2 child3 = new TestChild2();

child3.hello();

TestAbstract child4 = new TestChild2();

child4.hello();



} // end main()


} // end class InheritMain12 



* 출력화면


x = 123

안녕하세요~

안녕하세요~


Hello~~

Hello~~ 



3. abstract를 사용한 메소드 오버라이딩과 다형성

- Animal 클래스로부터 Move()를 상속받아 각 동물의 행동에 대해 메소드를 선언해줌

- 각 하위 클래스들을 불러옴으로써 다형성을 이용


* Animal.java (부모 클래스, 동물 이름 변수 및 움직임 메소드 선언)


package edu.java.inherit13;


public abstract class Animal {

// 멤버 변수

private String name;

// 생성자

public Animal(String name){

this.name = name;

}

public String getName(){

return name;

}

// 추상 메소드 선언

public abstract void Move();




* Dog.java (자식 클래스, 개의 행동 메소드 선언)


package edu.java.inherit13;


public class Dog extends Animal {


public Dog(String name) {

super(name);

// TODO Auto-generated constructor stub

}


@Override

public void Move() {

System.out.println(getName() + "는 총총...");

}


} // end class Dog 



* Kangaroo.java (자식 클래스, 캥거루의 행동 메소드 선언)


package edu.java.inherit13;


public class Kangaroo extends Animal {


public Kangaroo(String name) {

super(name);

}


@Override

public void Move() {

System.out.println(getName() + "는 껑충껑충...");


}


}




* Fish.java (자식 클래스, 물고기의 행동 메소드 선언)


package edu.java.inherit13;


public class Fish extends Animal {


public Fish(String name) {

super(name);

// TODO Auto-generated constructor stub

}


@Override

public void Move() {

System.out.println(getName() + "는 스윙스윙...");


}


} // end class Fish 



* InheritMain13


package edu.java.inherit13;


public class Fish extends Animal {


public Fish(String name) {

super(name);

// TODO Auto-generated constructor stub

}


@Override

public void Move() {

System.out.println(getName() + "는 스윙스윙...");


}


} // end class Fish


* 출력화면


강아지는 총총...

캥거루는 껑충껑충...

금붕어는 스윙스윙...


코멘트 : 각 클래스의 move()를 출력 메시지를 다르게 설정하여 객체 클래스 호출을 가능하게 함 



Comments