Java 8장. 상속 public class SumTest { public static void main(String a1[]) { int a, b, sum; a = Integer.parseInt(a1[0]); b = Integer.parseInt(a1[1]); sum = a + b ; // 두 수를 더하는 부분입니다 System.out.println("두수의 합은 " + sum + "입니다"); }
학습목표 클래스의 계층 구조와 상속에 관해 학습한다. 상속관계의 클래스에서 멤버 변수의 상속에 관해 학습한다. 상속관계의 클래스에서 메소드의 치환(Overriding)에 관해 학습한다. 상속관계의 클래스에서 생성자의 사용에 관해 학습한다. 상속관계에서 객체의 형변환에 관해 학습한다. 예약어 super, final 연산자 instanceof에 관해 학습한다.
목차 section 1 상속(Inheritance)의 개요 section 2 멤버 변수의 상속 section 3 메소드의 상속과 오버라이딩(Overriding) section 4 예약어 super section 5 속과 생성자 section 6 객체의 형변환 section 7 연산자 instanceof section 8 추상 클래스와 추상 메소드 section 9 예약어 final
상속(inheritance) 형식 1 상속(Inheritance)의 개요 객체지향 언어의 장점인 모듈의 재사용(reusing)과 코드의 간결성을 제공하는 중요한 특성 [public/final/abstract] class 클래스이름 extends 상위 클래스이름 { .......... 멤버 변수선언 .......... 생성자선언 .......... 메소드선언 } 형식 public class Box extends SuperBox { ..................... } public class MyApplet extends Applet {
protected 접근 한정자 멤버 변수의 접근 한정자 2 멤버 변수의 상속 같은 패키지 내의 클래스와 같은 패키지는 아니지만 상속된 클래스에서 사용 가능한 접근 한정자 멤버 변수의 접근 한정자 public : 동일한 패키지인지, 상속관계인지에 상관없이 모든 클래스에서 사용 가능 한정자 없음 : 동일한 패키지이면 상속 여부에 상관없이 사용 가능 protected : 동일한 패키지이면 상속 여부에 상관없이 사용 가능하며, 다른 패키지라도 상속되었으면 사용 가능 private : 어떠한 경우에도 사용 불가능. 클래스 내부에서만 사용 가능
2 멤버 변수의 상속 접근 한정자의 사용 247 page
실습예제 2 멤버 변수의 상속 InheritanceTest1.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 class A { int aa = 1; } class B extends A { int bb = 2; class C extends B { int cc = 3; public class InheritanceTest1 { public static void main(String[] args) { C objc = new C(); System.out.println ("objc객체의 객체속성변수 aa의 값은 " + objc.aa); ("objc객체의 객체속성변수 bb의 값은 " + objc.bb); ("objc객체의 객체속성변수 cc의 값은 " + objc.cc); 세 개의 클래스가 상속 관계 상속된 객체 변수에 접근
2 멤버 변수의 상속 프로그램 설명 04, 07 : 클래스 A, B, C가 상속관계로 정의되었고, 각 클래스는 하나의 객체 변수를 가지고 있다. 객체 변수가 접근 한정자를 가지고 있지 않으므로, 동일한 패키지에서는 상속된다. 14~17 : 클래스 C로부터 생성된 객체를 통하여 상속받은 변수 aa와 bb에 접근하여 값을 출력한다.
실습예제 2 멤버 변수의 상속 InheritanceTest2.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 class AA { int i; private int j; void setij(int x, int y) { i = x; j = y; } class BB extends AA { int total; void sum() { total = i + j; public class InheritanceTest2 { public static void main(String args[]) { BB subOb = new BB(); subOb.sum(); 객체 변수 j를 private로 선언 AA 클래스로부터 상속받아 BB 클래스 생성 오류 발생
프로그램 설명 2 멤버 변수의 상속 03 : 클래스 AA에서 객체 변수 j를 private로 선언하였다. 09 : 클래스 AA로부터 상속받아 클래스 BB를 생성하였다. 이 경우 상위 클래스에서 private로 선언된 객체 변수는 상속되지 않는다. 12 : 하위 클래스에서 상위 클래스의 private 변수에 접근하면 오류가 발생한다.
실습예제 2 멤버 변수의 상속 InheritanceTest3.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 class B1 { int x; } class B2 extends B1 { String x; public class InheritanceTest3 { public static void main(String args[]) { B2 b2 = new B2(); b2.x = "알기 쉽게 해설한 자바"; System.out.println("객체 b2에 들어있는 x 값 : " + b2.x); B1 b1 = new B1(); b1.x = 5000; System.out.println("객체 b1에 들어있는 x 값 : " + b1.x); 객체 변수 x 선언 객체 변수 x 선언. 상위 클래스의 객체 변수 x가 가려짐 x는 하위 클래스에서 선언된 문자열 x는 상위 클래스에서 선언된 정수
프로그램 설명 2 멤버 변수의 상속 02 : 상위 클래스에서 객체 변수 x를 선언하였다. 10 : B2 클래스로부터 생성된 객체를 통하여 접근하는 x는 당연히 String x 이다. 13 : B1 클래스로부터 생성된 객체를 통하여 접근하는 x는 당연히 int x 이다.
실습예제 2 멤버 변수의 상속 InheritanceTest4.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 class C1 { static int x; static int y; } class C2 extends C1 { static String x; class InheritanceTest4 { public static void main(String args[]) { C2.x = "알기 쉽게 해설한 자바"; C1.x = 30000; C1.y = 20000; System.out.println ("클래스 변수 C2.x 값 : " + C2.x); ("클래스 변수 C2.y 값(C1으로부터 상속) : " + C2.y); ("클래스 변수 C1.x 값 : " + C1.x); 두 개의 클래스 변수 선언 상속된 클래스에서 같은 이름을 가진 클래스 변수 선언 클래스 이름을 통하여 클래스 변수에 값 저장
2 멤버 변수의 상속 프로그램 설명 06 : 상속된 클래스에서 상위 클래스에 선언된 클래스 변수와 같은 이름의 클래스 변수를 선언하였다. 상위 클래스의 클래스 변수는 하위 클래스의 클래스 변수에 의해 가려지게 된다. 10~12 : 클래스 변수에 값을 설정하였다. 클래스 변수이기 때문에 클래스 이름을 통해서 접근하게 된다. 16 : C2.y 값은 클래스 C1으로부터 상속된 클래스 변숫값이 출력된다.
3 메소드의 상속과 오버라이딩(Overriding) 상속 관계에 있는 클래스들 간에 같은 이름의 메소드를 정의하는 경우 상위 클래스의 메소드와 하위 클래스의 메소드가 메소드 이름은 물론 매개변수의 타입과 개수까지도 같아야 함
3 메소드의 상속과 오버라이딩(Overriding) 실습예제 MethodInheritanceTest.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class AAA { int i; int j; void setij(int x, int y) { i = x; j = y; } class BBB extends AAA { int total; void sum() { total = i + j; public class MethodInheritanceTest { public static void main(String args[]) { BBB subOb = new BBB(); subOb.setij(10, 12); subOb.sum(); System.out.println ("두 수의 합계는 : " + subOb.total); 클래스 AAA로부터 객체 변수와 메소드가 상속 상속된 메소드 호출
3 메소드의 상속과 오버라이딩(Overriding) 프로그램 설명 09 : 상위 클래스 AAA로부터 객체 변수와 메소드를 상속받았다. 18 : 하위 클래스로부터 생성된 객체를 통하여 상위 클래스로부터 상속받은 메소드를 수행하였다.
3 메소드의 상속과 오버라이딩(Overriding) 실습예제 MethodInheritanceTest.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 class Da { void show(String str) { System.out.println ("상위 클래스의 메소드 show(String str)수행 " + str); } class Db extends Da { void show() { System.out.println("하위클래스의 메소드 show() 수행"); public class OverridingTest1 { public static void main(String args[]) { Db over = new Db(); over.show("알기 쉽게 해설한 자바"); over.show(); 매개변수가 있는 show() 메소드 선언 하위 클래스에서 매개변수가 없는 show() 메소드 선언
3 메소드의 상속과 오버라이딩(Overriding) 프로그램 설명 02, 08 : 상속된 관계의 클래스에서 상위 클래스에 선언된 메소드를 하위 클래스에서 오버라이딩하기 위해서는 메소드의 이름은 물론 매개변수의 개수와 형이 같아야 한다. 여기서는 매개변수의 개수와 형이 다르기 때문에 상위 클래스에 선언된 show(String str) 메소드가 하위 클래스에 상속된다. 15, 16 : 상속된 하위 클래스 입장에서 보면 같은 이름의 메소드가 상속되었으므로, 오버로딩이 되어 메소드가 호출될 수 있다.
3 메소드의 상속과 오버라이딩(Overriding) 실습예제 OverridingTest2.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 class Ea { void show() { System.out.println ("상위 클래스의 메소드 show(String str) 수행"); } class Eb extends Ea { System.out.println("하위클래스의 메소드 show() 수행"); public class OverridingTest2 { public static void main(String args[]) { Eb over = new Eb(); over.show(); 상속된 관계에서 동일한 메소드 선언(Overriding) 상속된 관계에서 동일한 메소드 선언(Overriding) 하위 클래스로 선언된 show() 메소드 수행
3 메소드의 상속과 오버라이딩(Overriding) 프로그램 설명 02, 08 : 상속된 두 개의 클래스에서 같은 이름과 매개변수를 가진 메소드를 오버라이딩하여 선언하였다. 상위 클래스에서 선언된 메소드는 하위 클래스의 메소드에 의해 가려지게 된다. 15 : 하위 클래스의 show() 메소드가 호출되어 수행된다.
예약어 super 형식 4 예약어 super 하위 클래스에 의해 가려진 상위 클래스의 멤버 변수나 메소드에 접근할 때 사용 상위 클래스의 생성자를 호출하기 위해 사용 super.객체 변수 super.메소드이름(매개변수) 형식
실습예제 4 예약어 super SuperTest1.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 class D1 { int x = 1000; void display() { System.out.println("상위 클래스 D1의 display() 메소드입니다"); } class D2 extends D1 { int x = 2000; System.out.println("하위클래스 D2의 display() 메소드 입니다"); void write() { display(); super.display(); System.out.println ("D2 클래스 객체의 x 값은 : " + x); display() 메소드를 오버라이딩 super를 사용하여 상위 클래스 메소드 수행
실습예제 4 예약어 super SuperTest1.java 18 19 20 21 22 23 24 25 26 27 ("D1 클래스 객체의 x 값은 : " + super.x); } class SuperTest1 { public static void main(String args[]) { D2 d = new D2(); d.write(); super를 사용하여 상위 클래스 객체 변수 사용
프로그램 설명 4 예약어 super 03, 10 : 상속된 관계의 클래스에서 같은 이름의 메소드를 오버라이딩하였다. 03, 10 : 상속된 관계의 클래스에서 같은 이름의 메소드를 오버라이딩하였다. 16 : 상위 클래스의 메소드를 수행시키기 위해 예약어 super를 사용하였다. 20 : 상위 클래스의 객체 변수를 사용하기 위해 예약어 super를 사용하였다.
묵시적(default) 생성자 super 문장 super-상위 클래스 생성자 호출 형식 5 상속과 생성자 성자 중에 매개변수가 없는 생성자 super 문장 상위 클래스의 특정 생성자를 호출하는 문장 반드시 생성자 부분의 첫 번째 라인에 위치 상위 클래스의 생성자가 항상 하위 클래스 생성자보다 먼저 수행되어야 함을 의미 super-상위 클래스 생성자 호출 super(매개변수) 형식
실습예제 5 상속과 생성자 SuperTest2.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 class A1 { double d1; A1() { System.out.println("클래스 A1의 생성자 수행"); d1 = 10*10; } class A2 extends A1 { double d2; A2() { System.out.println("클래스 A2의 생성자 수행"); d2 = 10*10*10; 상속관계의 클래스에서 묵시적 생성자 선언 상속관계의 클래스에서 묵시적 생성자 선언
실습예제 5 상속과 생성자 SuperTest2.java 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class A3 extends A2 { double d3; A3() { System.out.println("클래스 A3의 생성자 수행"); d3 = 10*10*10*10; } class SuperTest2 { public static void main(String args[]) { A3 super1 = new A3(); System.out.println("10의 2제곱 : " + super1.d1); System.out.println("10의 3제곱 : " + super1.d2); System.out.println("10의 4제곱 : " + super1.d3); 상속관계의 클래스에서 묵시적 생성자 선언 하위 클래스로부터 객체 생성. 상위 클래스 묵시적 생성자 수행
5 상속과 생성자 프로그램 설명 03, 10, 17 : 3개의 클래스가 상속관계를 이루고 있으면서, 묵시적인 생성자를 모두 가지고 있다. 24 : 최하위 클래스에서 객체를 생성하면, 상위 클래스의 묵시적 생성자들이 먼저 수행된다. 즉 new 문장에 의해 객체가 생성되면 묵시적 생성자는 무조건 수행된다.
실습예제 5 상속과 생성자 SuperTest3.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 class Ad1 { int d1; int s; Ad1(int s1) { System.out.println("클래스 Ad1의 생성자 수행"); s = s1; d1 = s * s ; } class Ad2 extends Ad1 { int d2; int t; Ad2(int s1, int t1) { super(s1); 매개변수가 있는 생성자 선언 하위 클래스의 생성자 첫 번째 라인에서 상위 클래스 생성자 호출
실습예제 5 상속과 생성자 SuperTest2.java 15 16 17 18 19 20 21 22 23 24 25 26 System.out.println("클래스 Ad2의 생성자 수행"); t = t1; d2 = t * t ; } public class SuperTest3 { public static void main(String args[]) { Ad2 super2 = new Ad2(10,20); System.out.println("10의 제곱은 : " + super2.d1); System.out.println("20의 제곱은 : " + super2.d2); 객체 생성. 생성자가 수행됨
자바는 클래스 계층 구조에서 상속관계의 클래스로부터 생성된 객체들 사이의 형변환을 허용 6 객체의 형변환 자바는 클래스 계층 구조에서 상속관계의 클래스로부터 생성된 객체들 사이의 형변환을 허용 class Acast { int a=1; } class Bcast extends Acast { int b=2; class Ccast extends Bcast { int c=3; public class TestCasting { public static void main(String[] args) { Acast refA; refA = new Ccast(); System.out.println("refA.a의 값은 "+refA.a); Acast 타입의 객체 refA 선언 Acast 타입의 객체 변수 refA에 Ccast 클래스의 객체를 생성하여 할당
메인 클래스를 다음과 같이 수정 6 객체의 형변환 public class TestCasting { public static void main(String[] args) { Acast refA; refA = new Ccast(); System.out.println("refA.a의 값은 "+refA.c); } Ccast 클래스 멤버에 접근. 오류 발생
Ccast형의 객체 변수로 refC를 선언하고, refC에 Acast형의 객체를 할당 6 객체의 형변환 Ccast형의 객체 변수로 refC를 선언하고, refC에 Acast형의 객체를 할당 public class TestCasting { public static void main(String[] args) { Ccast refC = new Acast(); System.out.println("refC.a의 값은 "+refC.a); } 오류 발생
6 객체의 형변환 클래스 사이에서 객체의 형변환 하위 클래스에서 생성된 객체를 상위 클래스 형의 객체 변수에 배정하는 형변환은 허용 반대로 상위 클래스에서 생성된 객체를 하위 클래스 형의 객체 변수에 배정할 수 없다. 상위 클래스 형의 객체 변수에 배정된 하위 클래스 객체의 경우, 상위 클래스 형의 객체 변수를 통해서는 상위 클래스에 선언된 속성에만 접근이 가능
실습예제 6 객체의 형변환 OverridingAndCasting.java 01 02 03 04 05 06 07 08 09 10 11 12 13 class Am { void callme() { System.out.println ("클래스 Am의 callme() 메소드 실행"); } class Bm extends Am { ("클래스 Bm의 callme() 메소드 실행"); 3개의 상속된 클래스에 메소드 오버라이딩 3개의 상속된 클래스에 메소드 오버라이딩
실습예제 6 객체의 형변환 OverridingAndCasting.java 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Cm extends Am { void callme() { System.out.println ("클래스 Cm의 callme() 메소드 실행"); } public class OverridingAndCasting { public static void main(String args[]) { Am r = new Am(); r.callme(); r = new Bm(); r = new Cm(); 3개의 상속된 클래스에 메소드 오버라이딩 Am 클래스의 객체 변수 r에 Am 클래스 객체 배정 Am 클래스의 객체 변수 r에 Bm 클래스 객체 배정 Am 클래스의 객체 변수 r에 Cm 클래스 객체 배정
6 객체의 형변환 프로그램 설명 26-27 : 이 문장을 실행시간 측면에서 살펴보면 Am 클래스 타입의 객체 변수 r에 Cm 클래스로부터 객체를 생성하여 할당하였다. 그리고 r을 통하여 callme() 메소드를 호출하고 있다. 객체 변수 r은 callme() 메소드에 접근할 수 있는 방법을 가지고 있고, Cm 클래스에서는 Am 클래스의 메소드 callme()를 오버라이딩하고 있다. 그러므로 실행시간에 수행되는 callme() 메소드는 Cm 클래스에 정의된 callme() 메소드이다.
instanceof 형식 7 연산자 instanceof 객체가 특정 클래스나 인터페이스로부터 생성된 객체인지를 판별하여 ture 또는 false 값을 반환하여 주는 이진 연산자 type : 클래스 이름 또는 인터페이스 이름 객체 변수 instanceof type 형식 if (oba instanceof String) System.out.println("oba는 String 클래스의 객체입니다");
실습예제 7 연산자 instanceof InstanceofAndCasting.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 class An { int i, j; } class Bn extends An{ int k; class Cn extends Bn { int m; public class InstanceofAndCasting { public static void main(String args[]) { An a = new An(); Bn b = new Bn(); Cn c = new Cn(); 3개의 클래스가 상속
실습예제 7 연산자 instanceof InstanceofAndCasting.java 15 16 17 18 19 20 21 22 23 24 25 26 27 28 if(a instanceof An) System.out.println("a는 A 클래스의 객체"); if(b instanceof Bn) System.out.println("b는 B 클래스의 객체"); if(c instanceof Cn) System.out.println("c는 C 클래스의 객체"); if(c instanceof An) System.out.println("c는 A 클래스의 객체 : 형변환"); if(a instanceof Cn) System.out.println("a는 C 클래스의 객체 : 형변환"); else System.out.println("a는 C 클래스의 객체가 아님 : 형변환 불가"); } 형변환 성공 형변환 불가
프로그램 설명 7 연산자 instanceof 01~09 : 3개의 클래스가 상속관계를 형성하고 있다. 01~09 : 3개의 클래스가 상속관계를 형성하고 있다. 12~23 : 각 클래스로부터 객체를 생성하여, 각 객체가 해당 클래스의 객체인지를 판별하였다. 21 : Cn 클래스로 생성된 객체 c가 An 클래스의 객체인지를 판별하고 있다. 객체 c의 클래스인 Cn 클래스는 An 클래스로부터 상속된 클래스이므로 Cn 클래스는 An 클래스의 모든 속성을 다 가지고 있다. 그러므로 하위 클래스 Cn으로부터 생성된 객체는 An클래스의 객체라 할 수 있다. 23 : 상위 클래스로부터 생성된 객체 a가 하위 클래스인 Cn 클래스의 객체인가를 판별하고 있다. 하위 클래스인 Cn은 상위 클래스인 An보다 추가적인 정보를 더 가진 클래스이다. 그러므로 객체 a가 Cn 클래스의 객체라 할 수 없다.
7 연산자 instanceof
추상 클래스 8 추상 클래스와 추상 메소드 하위 클래스에서 구현되는 추상적인 기능만을 정의하는 클래스 추상 클래스에서 정의된 추상적인 기능은 하위 클래스에서 구현 271 page
추상 메소드 추상 클래스와 추상 메소드 형식 8 추상 클래스와 추상 메소드 추상 클래스 내에 정의되는 메소드로써 선언 부분만 있고 구현 부분이 없는 메소드 하위 클래스에서는 상위 클래스에서 추상 메소드로 정의된 메소드를 오버라이딩하여 사용 추상 클래스와 추상 메소드 abstract class 클래스이름 { ........... 클래스에 기술할 수 있는 일반적인 멤버 변수와 메소드 abstract void 추상메소드이름(); } 형식 추상 메소드는 선언 부분만 있다. 하위 클래스에서 오버라이딩하여 사용
추상 클래스와 추상 메소드 8 추상 클래스와 추상 메소드 abstract class Shape { ............. abstract void draw(); } public class Circle entends Shape { void draw() { 실제 원을 그리는 기능이 기술됨; public class Triangle entends Shape { 실제 삼각형을 그리는 기능이 기술됨; 같은 이름의 메소드를 선언함으로서 오버라이딩
실습예제 8 추상 클래스와 추상 메소드 AbstractTest.java 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 abstract class Shape { abstract void draw(); abstract void computeArea(double a, double b); } class Circle extends Shape { void draw() { System.out.println("원을 그리는 기능"); void computeArea(double r1, double r2) { System.out.println("원의 넓이 : " + (3.14 * r1 * r2)); class Rectangle extends Shape { System.out.println("사각형을 그리는 기능"); void computeArea(double h, double v) { System.out.println("사각형의 넓이 : " + (h * v)); 추상 클래스와 추상 메소드 선언
실습예제 8 추상 클래스와 추상 메소드 AbstractTest.java 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class Triangle extends Shape { void draw() { System.out.println("삼각형을 그리는 기능"); } void computeArea(double a, double h) { System.out.println("삼각형의 넓이 : " + (a * h / 2)); public class AbstractTest { public static void main(String args[]) { Circle c = new Circle(); c.draw(); c.computeArea(5.0, 5.0); Rectangle r = new Rectangle(); r.draw(); r.computeArea(5.0, 10.0); Triangle t = new Triangle(); t.draw(); t.computeArea(5.0, 10.0); 서로 다른 객체에 같은 이름의 메소드 사용 서로 다른 객체에 같은 이름의 메소드 사용 서로 다른 객체에 같은 이름의 메소드 사용
실습예제 8 추상 클래스와 추상 메소드 AbstractTest.java 41 42 43 44 45 46 47 48 49 50 51 52 System.out.println("==객체 형변환과 오버라이딩을 이용=="); Shape s = new Circle(); s.draw(); s.computeArea(5.0, 5.0); s = new Rectangle(); s.computeArea(5.0, 10.0); s = new Triangle(); } 객체의 형변환을 이용하여 동일한 메소드에 대해 서로 다른 결과 출력
프로그램 설명 8 추상 클래스와 추상 메소드 01~04 : 두 개의 추상 메소드를 가진 추상 클래스를 선언하였다. 01~04 : 두 개의 추상 메소드를 가진 추상 클래스를 선언하였다. 05~28 : 추상 클래스 Shape를 상위 클래스 하여 세 개의 클래스를 생성하였으며, 각각의 클래스에 추상 메소드를 오버라이딩하여 구현하였다. 각각의 클래스에서 오버라이딩하여 구현된 메소드의 내부는 당연히 다르게 작성된다. 32~40 : 각 클래스로부터 객체를 생성하여 draw() 메소드와 computeArea() 메소드를 수행시켰다. 서로 다른 객체이지만 동일한 메소드를 이용하여 도형을 그리고, 면적을 계산하였다. 42~50 : 상위 클래스인 추상 클래스 형의 객체 변수를 선언하고 그 변수에 하위 클래스의 객체를 배정하였다. 오버라이딩과 객체의 형변환을 이용하여 동일한 메시지 s.draw(), s.computeArea() 에 대해 서로 다르게 응답하는 예를 보이고 있다.
8 추상 클래스와 추상 메소드
Final 메소드에 final을 붙여 사용 9 예약어 final 자바에서 3가지로 사용 class A { final void calculate() { System.out.println("이 메소드는 final 메소드"); } class B extends A { void calculate() { System.out.println("final 메소드를 중첩하는 메소드"); 오류 발생. 상위 클래스에서 final로 선언된 메소드는 오버라이딩 금지
클래스에도 final을 붙여 사용 9 예약어 final final class A { .......... } class B extends A { ......... 오류 발생
학습정리 상속의 개요 멤버 변수의 상속 상속은 객체지향의 주요 특성인 모듈의 재사용과 코드의 간결성을 제공한다. 자바에서 모든 프로그램은 상위 클래스를 가진다. 상속은 확장의 개념으로 상위 클래스의 모든 요소를 상속받고 추가 요소를 더 가지는 개념이다. 멤버 변수의 상속 클래스가 상속되면 상위 클래스에 선언된 멤버 변수는 접근 한정자에 따라 상속 여부가 결정된다. protected 접근 한정자는 같은 패키지 내의 클래스와 같은 패키지는 아니지만, 상속된 클래스에서 사용 가능한 접근 한정자이다.
학습정리 메소드의 상속과 오버라이딩 예약어 super 클래스가 상속되면 상위 클래스에 선언된 메소드도 접근 한정자에 따라 상속 여부가 결정된다. 상위 클래스에서 선언된 메소드와 똑같은 메소드를 하위 클래스에 선언하는 것을 오버라이딩이라 한다. 상속관계에서 메소드가 오버라이딩되면 상위 클래스의 메소드는 가려지게 된다. 예약어 super super는 하위 클래스에 의해 가려진 상위 클래스의 멤버 변수나 메소드에 접근할 때 사용한다. 상위 클래스의 생성자를 호출할 때도 사용한다.
학습정리 상속과 생성자 객체의 형변환 추상 클래스와 추상 메소드 상속관계에서 매개변수가 없는 생성자(묵시적 생성자)는 하위 클래스에서 객체가 생성될 때 자동으로 수행된다. 묵시적 생성자가 아닌 경우에는 명시적으로 super를 사용하여 호출하여야 한다. 객체의 형변환 상속관계의 클래스로부터 생성된 객체들 사이의 형변환을 허용한다. 상위 클래스형으로 선언된 객체 변수에 하위 클래스로부터 생성된 객체를 배정할 수 있으며, 이 경우 상위 클래스에 선언된 요소만 접근이 가능하다. 추상 클래스와 추상 메소드 추상 클래스는 하위 클래스에서 구현되는 추상적인 기능만을 정의하는 클래스로서 추상 메소드를 가지는 클래스이다. 추상 클래스는 기능이 무엇(what)인지만 정의하고, 어떻게(how) 구현되어 있는지는 정의하지 않는다. 어떻게 구현되었는지는 하위 클래스에서 정의한다.
8장. 상속 수고하셨습니다. 질문 있습니까?