------------------------------
상속 (Inheritance)
7. 하위 클래스는 한 개만의 상위 클래스를 선택할 수 있다. 단일 상속. 상위 클래스는 파생을 염두해두고 자신의 멤버를 상속 가능한 상태로 만드는 것이 일반적이다. 하위 클래스는 모든 상위 클래스를 스스로 선택할 수 있다. 상위 클래스는 하위 클래스가 가지게 될 공통적인 특성만 멤버로 구성하는 경우가 많다. 하위 클래스는 개별적인 특성을 구성하게 된다.
8. 상위 클래스의 멤버와 같은 이름을 가진 멤버를 하위 클래스에 재구성해서 사용할 수 있다. 오버라이딩(Overriding).
오버라이딩 기본 조건
- 상위 클래스의 멤버와 동일한 이름, 메소드 시그니처, 리턴타입을 가진 메소드
- 접근지정자는 상위 클래스와 다르게 지정할 수 있다. 단, 상위 클래스보다 좁은 범위로의 지정은 안된다.
- 더 적은 예외를 지정할 수 없다.
- static, instance 상태를 변경할 수 없다.
//Super01.java
package com.test;
//최상위 클래스 -> Object
//상위 클래스 역할
public class Super01 {
//상위 클래스의 멤버 추가
public void method() {
System.out.println("Super01 클래스의 method() 호출!");
}
//Object 클래스의 멤버를 오버라이딩 가능
//-> toString()
}
//Sub01.java
package com.test;
public class Sub01 extends Super01 {
//Sub01 클래스의 고유 멤버 추가
public void method2() {
System.out.println("Sub01 클래스의 method2() 호출!");
}
//Super01 클래스의 멤버(method() 메소드) 오버라이딩
//Super01 클래스의 멤버 구성을 동일하게 작성.
/*@Override는 오버라이딩되는 메소드임을 표시하는 주석*/
@Override
public void method() {
//메소드 내부 내용은 새로 지정합니다.
System.out.println("Sub01 클래스의 method() 호출!");
}
//Object 클래스의 멤버를 오버라이딩 가능
//-> toString()
//-> 인스턴스의 정보 반환
//-> 패키지.클래스@해쉬코드
@Override
public String toString() {
//메소드 내부 내용은 새로 지정합니다.
return "Sub01 클래스의 toString() 호출!";
}
}
//Sub02.java
package com.test;
public class Sub02 extends Sub01 {
//멤버가 없는 상태
//-> Object, Super01, Sub01 클래스의 멤버 공유 가능
}
//Main.java
package com.test;
public class Main {
public static void main(String[] args) {
Super01 super01 = new Super01();
super01.method();
System.out.println(super01.toString());
Sub01 sub01 = new Sub01();
sub01.method2();
//오버라이딩 메소드 호출
sub01.method();
//오버라이딩 메소드 호출
System.out.println(sub01.toString());
Sub02 sub02 = new Sub02();
System.out.println(sub02.toString());
sub02.method(10);
String str = new String("TEST");
//오버라이딩 메소드 호출
System.out.println(str.toString());
Integer a = new Integer(10);
//오버라이딩 메소드 호출
System.out.println(a.toString());
Sub02 b = new Sub02();
Sub02 c = new Sub02();
System.out.println(b.equals(c)); //false
Sub02 d = b;
System.out.println(b.equals(d)); //true
String e = new String("TEST");
String f = new String("TEST");
//오버라이딩 메소드 호출
System.out.println(e.equals(f)); //true
Integer g = new Integer(10);
Integer h = new Integer(10);
//오버라이딩 메소드 호출
System.out.println(g.equals(h)); //true
}
}
--------------------------
객체의 크기 비교
//기본 자료형, 문자열 자료형, 사용자 정의 클래스 자료형 크기 비교
//Sample100.java
package com.test;
public class Sample100 {
public static void main(String[] args) {
//기본자료형의 자료는 비교 연산자로 크기 비교 가능
//-> >, <, >=, <=, ==, !=
int a = 10;
int b = 20;
System.out.println(a>b); //false
System.out.println(a<b); //true
System.out.println(a==b); //false
System.out.println(a!=b); //true
//Wrapper Class는 내부적으로 암시적 형변환 지원
Integer c = new Integer(10);
Integer d = new Integer(20);
System.out.println(c>d); //암시적 형변환. Integer->int
System.out.println(c<d); //암시적 형변환. Integer->int
//참조자료형의 자료는 비교 연산자로 크기 비교 불가능.
String g = new String("A");
String h = new String("B");
//System.out.println(g>h); //X
//System.out.println(g<h); //X
//compareTo() 메소드는 문자열 비교시 사용하는 메소드
//결과값은 0(문자열이 동일한 경우), 음수(-1), 양수(1)
System.out.println(g.compareTo(h)); //-1 -> g<h
System.out.println(h.compareTo(g)); //1 -> g<h
String[] result = {"h가 큽니다", "같습니다", "g가 큽니다."};
System.out.println(result[g.compareTo(h)+1]);
//사용자 정의 클래스에 대한 객체의 크기 비교
//객체는 크기 비교 불가능
//동일 자료형을 가진 객체 내부에 있는 데이터 값을 가지고 비교 가능
//-> compareTo() 메소드 구현 필요
UserInteger e = new UserInteger(30);
UserInteger f = new UserInteger(20);
//System.out.println(e>f); //X
//System.out.println(e<f); //X
if (e.compareTo(f) == 0) {
System.out.println("같습니다.");
} else if (e.compareTo(f) > 0) {
System.out.println("e가 큽니다.");
} else {
System.out.println("f가 큽니다.");
}
}
}
//UserInteger.java
package com.test;
public class UserInteger {
private int a;
//기본생성자 생략
//매개변수가 있는 생성자만 작성
public UserInteger(int a) {
this.a = a;
}
public int getA() {
return this.a;
}
//객체에 전달된 데이터를 비교하는 전용 메소드 추가
//->compareTo()
//->결과는 0, 양수, 음수가 나오도록 작성
public int compareTo(UserInteger obj) {
//0(동일), 음수(작다), 양수(크다)
return this.a - obj.getA();
}
}
--------------------------------------------------
//Member.java
package com.test;
public class Member {
private String name, tel;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
}
//MemberMain.java
package com.test;
import java.util.*;
public class MemberMain {
public static void main(String[] args) {
Member[] members = new Member[5];
Member member0 = new Member();
member0.setName("kim");
member0.setTel("010-123-1234");
members[0] = member0;
Member member1 = new Member();
member1.setName("choi");
member1.setTel("010-432-4321");
members[1] = member1;
Member member2 = new Member();
member2.setName("park");
member2.setTel("010-567-5678");
members[2] = member2;
Member member3 = new Member();
member3.setName("kang");
member3.setTel("010-543-5678");
members[3] = member3;
Member member4 = new Member();
member4.setName("hong");
member4.setTel("010-987-9876");
members[4] = member4;
//정렬 전
System.out.println("정렬 전:");
for (Member member : members) {
//System.out.println(member);
//System.out.println(member.toString());
System.out.printf("%s %s %n"
, member.getName()
, member.getTel());
}
//배열 요소 정렬 과정 추가
//객체의 멤버(값)을 기준으로 정렬하는 과정 -> Comparator 구현 필요
Arrays.sort(members, new Comparator<Member>() {
//객체의 값 비교하는 메소드에 대해서
//오버라이딩
//-> 결과값 0, 양수, 음수
@Override
public int compare(Member o1, Member o2) {
//객체의 값(name)을 비교하는 과정 추가
//멤버 name-> String -> compareTo() 메소드
return o1.getName().compareTo(o2.getName());
}
});
//정렬 후 (이름 오름차순)
System.out.println("정렬 후:");
for (Member member : members) {
System.out.printf("%s %s %n"
, member.getName()
, member.getTel());
}
}
}
---------------------------------------------
과제) Student 클래스 작성.
Student 클래스의 멤버 구성은 name, kor, eng, mat, tot로 만든다.
Student 클래스의 객체 여러개를 생성해서
Students 배열에 저장한다.
Student 객체의 멤버변수에 값(name, kor, eng, mat)을
입력하는 과정은 생성자를 이용한다. (setter 이용 가능)
tot(총점) 기준으로 정렬 전 상태와 정렬 후 상태를 출력한다.
실행 예)
입력 범위(2~n)?3
학생1(name kor eng mat)?kim 100 90 80
학생2(name kor eng mat)?choi 100 100 100
학생3(name kor eng mat)?park 70 90 100
정렬 전:
kim 100 90 80 270
choi 100 100 100 300
park 70 90 100 260
정렬 후:
choi 100 100 100 300
kim 100 90 80 270
park 70 90 100 260
//Student.java
package com.test;
public class Student {
//이름, 국어, 영어, 수학
private String name;
private int kor, eng, mat;
public Student() {
}
public Student(String name, int kor, int eng, int mat) {
this.name = name;
this.kor = kor;
this.eng = eng;
this.mat = mat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getKor() {
return kor;
}
public void setKor(int kor) {
this.kor = kor;
}
public int getEng() {
return eng;
}
public void setEng(int eng) {
this.eng = eng;
}
public int getMat() {
return mat;
}
public void setMat(int mat) {
this.mat = mat;
}
//총점 반환용 메소드 추가
public int getTotal() {
return this.kor + this.eng + this.mat;
}
}
//Main.java
package com.test;
import java.util.*;
public class Main {
public static void main(String[] args) {
//입력
Scanner sc = new Scanner(System.in);
System.out.print("입력 범위(1~n)?");
int size = sc.nextInt();
//배열 선언 -> Student 객체 저장용 -> Student 자료형 지정
Student[] array = new Student[size];
for (int i=0; i<array.length; ++i) {
System.out.print("이름 국어 영어 수학?");
String name = sc.next();
int kor = sc.nextInt();
int eng = sc.nextInt();
int mat = sc.nextInt();
//방법1 -> 생성자 이용
//Student s = new Student(name, kor, eng, mat);
//방법2 -> setter 이용
Student s = new Student();
s.setName(name);
s.setKor(kor);
s.setEng(eng);
s.setMat(mat);
array[i] = s;
}
sc.close();
//출력(정렬 전)
System.out.println("정렬 전:");
for (Student s : array) {
System.out.printf("%s %d %d %d %d %n"
, s.getName()
, s.getKor()
, s.getEng()
, s.getMat()
, s.getTotal());
}
//처리(정렬 과정)
//-> Arrays.sort() 메소드 호출
//배열의 자료형이 기본형인 경우 -> Arrays.sort(배열);
//배열의 자료형이 참조형인 경우 -> Arrays.sort(배열, 크기 비교 기준 제시->Comparator);
Arrays.sort(array, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//결과값 -> 0, 양수, 음수
//비교 기준 -> String -> compareTo() 메소드
//비교 기준 -> int -> 빼기 연산
//오름 차순 -> o1 원본, o2 비교 대상
//내림 차순 -> 반대
return o2.getTotal() - o1.getTotal();
//return o1.getName().compareTo(o2.getName());
}
});
//출력(정렬 후)
System.out.println("정렬 후:");
for (Student s : array) {
System.out.printf("%s %d %d %d %d %n"
, s.getName()
, s.getKor()
, s.getEng()
, s.getMat()
, s.getTotal());
}
}
}
----------------------------------------------
9. super 키워드는 상위 클래스의 객체를 접근하는 방법이다.
10. 하위 클래스의 객체를 생성하게 되면, 내부적으로 상위 클래스의 객체는 자동 생성된다. super() 생성자 호출 부분 생략된 상태.
11. super()는 상위 클래스의 생성자를 호출하는 구문이다. 하위 클래스의 객체 생성 과정에서 상위 클래스의 객체 생성은 자동 호출된다. 상위 클래스의 매개변수가 있는 생성자를 호출할 때 super() 를 사용한다.
12. 기본생성자가 없는 클래스를 하위 클래스가 상속 받는 경우 super() 생성자 호출 과정이 작동하지 않게 되기 때문에 문제가 발생한다.
//Super.java
package com.test;
public class Super {
//기본 생성자가 없으면 자동 생성된다.
//->컴파일러가 자동 생성해준다.
//하위클래스에서 객체 생성시 자동 호출될 예정이다.
//생략된 생성자를 표기한다면 아래와 같다.
public Super() {
super(); //Object 클래스의 기본 생성자 호출
}
public void superMethod() {
}
}
//Sub.java
package com.test;
public class Sub extends Super {
//기본 생성자가 없으면 자동 생성된다.
//->컴파일러가 자동 생성해준다.
//기본 생성자가 호출될 때 상위 클래스의 생성자도 같이 호출된다.
//->super() 가 생략된 상태
//생략된 생성자를 표기한다면 아래와 같다.
public Sub() {
super(); //Super 클래스의 기본생성자 호출
}
public void subMethod() {
}
}
//Sample82.java
package com.test;
public class Sample82 {
public static void main(String[] args) {
//Sub 클래스의 객체 생성시
//Sub() 구문에 의해서
//Sub 생성자가 호출된다.
Sub sub = new Sub();
sub.subMethod();
sub.superMethod();
}
}
//Super.java
package com.test;
//상위 클래스
//내부적으로 Object 클래스를 상속 받고 있다.
public class Super {
//기본 생성자 생략
//기본 생성자 내부에서 상위 클래스 생성자 호출 구문 생략
/*
public Super() {
super(); //Object 클래스의 기본 생성자 호출
}
*/
}
//Sub.java
package com.test;
//하위 클래스 -> Super 클래스를 상위 클래스로 지정
public class Sub extends Super {
private int a;
//기본 생성자 생략
//기본 생성자 내부에서 상위 클래스 생성자 호출 구문 생략
/*
public Sub() {
super(); //Super 클래스의 기본 생성자 호출
}
*/
//매개변수가 있는 생성자 추가
//->기본 생성자는 자동 생성되지 않게 된다.
//->현재 클래스를 상속받은 하위 클래스는 객체 생성 과정에서 문제 발생 가능.
public Sub(int a) {
this.a = a;
}
}
//Sub2.java
package com.test;
public class Sub2 extends Sub { //X
//상위 클래스에서 기본생성자가 존재하지 않으므로
//현재 클래스는 기본생성자를 사용할 수 없는 상태가 된다.
//->super() 호출 불가능
}
13. 상속관계는 is-a(~은 ~이다) 관계를 가진다.
14. 클래스 간의 포함 관계를 맺어 주는 것은
클래스의 멤버변수로 다른 클래스를 선언하는 것을 뜻한다.
포함 관계는 has-a(~은 ~을 가지고 있다) 관계이다.
------------------------------------------------------
'JavaSE' 카테고리의 다른 글
21일차_제어자, 싱글톤, 회원관리_배열 (0) | 2015.06.21 |
---|---|
20일차_메소드 오버로딩, 메소드 오버라이딩, 메인메뉴 액션 (0) | 2015.06.21 |
18일차_상속 (0) | 2015.06.21 |
17일차_멤버변수 (0) | 2015.06.21 |
16일차_생성자 (0) | 2015.06.21 |