객체지향언어의 3대특징 - 은닉성(캡슐화), 상속성, 다형성
※ 상속 (Inheritance)
- 부모 클래스의 구성요소, 행위를 그대로 물려받아 사용하고, 자신만의 구성요소와 행위는 추가해서 사용
- 클래스를 상속받게 되면 부모 클래스의 멤버들을 가져다가 사용할 수 있다
- 자식 클래스들의 공통적인 부분은 부모 클래스에서 관리하고, 자식클래스는 자신에 정의된 멤버들만 관리
▶ 상속의 장점
- 적은양의 코드로 새로운 클래스 작성 가능
- 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 용이
부모클래스 ) 상위 (Super) 클래스, 기본(Base) 클래스, 조상클래스
자식클래스 ) 하위(sub) 클래스, 파생 (derived) 클래스, 자손클래스
- 클래스간의 상속관계를 맺어주면 자식 클래스들의 공통적인 부분은 부모클래스에서 관리하고 자식클래스는 자신에 정의된 멤버들만 관리하면되므로 각 클래스의 코드가 적어져서 관리가 쉬워짐
▷ 자식 클래스의 멤버개수는 부모클래스와 같거나 많다
자식클래스 멤버 >= 부모클래스
class 자식클래스명 extends 부모클래스명
class Son extends Parent
protected = 같은 패키지는 물론 다른 패키지일지라도 상속관계가 있으면 접근 가능
(상속받은 자식 클래스에서 접근 가능)
- 외부에 자신의 멤버를 감추고 자식클래스에게만 멤버를 노출함
- 실행타임에는 default 클래스 (=클래스 외부에서 보면 default 로 보임)
디자인타임에 자식에게는 public
▶ 상속의 특징
- 생성자는 상속되지않음. 멤버만 상속됨
- 생성자는 상위클래스로부터 '상속' 되지 않고 '호출' 됨 ( 메모리는 최상위 클래스부터 차례대로 생성됨 )
- 클래스는 중복상속이 불가하며 단일 상속만 가능함
- 단계별상속 : 상위 레벨의 생성자가 차례대로 호출되어지고, 제일 마지막에 자신의 것이 호출됨
※ Object 클래스 ( 모든 클래스의 조상 )
- 모든 클래스 상속 계층도의 제일 위에 위치하는 조상 클래스
- 다른 클래스로부터 상속받지 않는 모든 클래스들은
자동적으로 Object 클래스로부터 상속받음
( = 자바의 모든 클래스들은 Object 클래스의 멤버들을 상속받음.
따라서 Object 클래스에 정의된 멤버들을 사용할 수 있다 ex) toString(), equals(Object o))
※ 자료형별 디폴트값
자료형 | default 값 |
int | 0 |
long | 0 |
double | 0.0 |
boolean | false |
String (or Object) | null |
※ 기본형 매개변수와 참조형 매개변수
기본형 매개변수 (call by value)
- 변수의 값을 읽기만 할 수 있다 (read only)
- 매개변수가 기본자료형, 값이 전달됨
=> 메서드에서 매개변수의 값을 변경해도 호출한 곳 (main) 에서는 변경의 영향을 받지 않음
참조형 매개변수 (call by reference)
- 변수의 값을 읽고 변경할 수 있다 (read & write)
- 매개변수가 참조형, 주소가 전달됨
=> 메서드에서 매개변수의 값을 변경하면 호출한곳(main) 에서도 변경의 영향을 받음
public class ValueTest {
public static void main(String[] args) {
Data d = new Data();
//기본
d.x=10;
System.out.println("main() : x="+d.x); //10
change(d.x);
System.out.println("메서드 호출 후 main(): x="+ d.x); //10
//class 가 매개변수인 경우
d.x=20;
System.out.println("\n----main() : x="+d.x); //20
change2(d);
System.out.println("change2() 호출 후 main():x="+d.x); //2000
//배열이 매개변수인경우
int[] arr = new int[2];
arr[0]=30;
arr[1]=40;
System.out.println("\n======main(): arr[0]="+arr[0]); //30
change3(arr);
System.out.println("change3() 호출 후 main() : arr[0]="+arr[0]); //3000
}
public static void change(int x) { //call by value
x=1000;
System.out.println("change() : x="+x); //1000
}
public static void change2(Data d) { //call by reference
d.x=2000;
System.out.println("change2() : x="+d.x); //2000
}
public static void change3(int[] arr) { //call by reference
arr[0]=3000;
System.out.println("change3() : arr[0]="+arr[0]); //3000
}
}
==> 기본형을 매개변수로 가진 경우 change 메서드를 호출해도 main() x의 값이 이전과 동일하지만
참조형 (클래스가 매개변수, 배열이 매개변수) 의 경우 change 메서드 호출 후 main() 값이 변경된것을 확인할 수 있다.
※ 오버라이딩 (Overriding)
- 부모 클래스로부터 상속받은 메서드의 내용을 변경하는 것 (= 메서드 재정의 )
▶ 오버라이딩 조건
1. 메서드의 선언부는 부모의 것과 완전히 일치해야 함
선언부 : 메서드명, 매개변수, 반환타입이 같아야 함
2. 접근 제한자는 부모 메서드보다 좁은 범위로 변경할 수 없다.
ex ) 부모 메서드가 protected 라면, 오버라이딩 메서드는 protected 나 public 이어야 함
접근제한자 : private < default < protected < public
3. 부모클래스의 메서드보다 많은 수의 예외를 선언할 수 없다
class Point{
protected int x;
protected int y;
public String findLocation() {
String result="x="+x+", y="+y;
return result;
}
} // 부모클래스
class Point3D extends Point{
private int z;
//오버라이딩 메서드
public String findLocation() {
String result=super.findLocation() + ", z="+z;
return result;
} // 자식클래스
// => 부모(super) 에서 findLocation메서드를 가져와 변수 z 를 추가한다
※ this / super
▶ this
- 다음 두 조건을 만족시킨다면 생성자간에도 서로 호출이가능함
1 ) 생성자의 이름으로 클래스 이름 대신 this 를 사용한다
2 ) 한 생성자에서 다른 생성자를 호출할때는 반드시 첫 줄에서만 호출이 가능하다
▷ this.멤버 : 자신의 멤버를 참조하는 this
▷ this () - 생성자를 호출하는 this()
- 같은 클래스 내의 Overloading 된 다른 생성자 메서드를 호출할 때 사용
- 다양한 변수들을 선택적으로 초기화하기위해 생성자를 다양하게 Overloading 하는건 알지 서현아
Overloading : 같은 클래스에서 메서드명은 같은데 매개변수의 개수나 자료형이 다른 것
lass Car{
private String color;
private String gearType;
private int door;
//기본형 생성자
Car(String color, String gearType, int door){
this.color=color;
this.gearType=gearType;
this.door=door;
}
Car(){
this("white","auto",4); //this 로 매개변수가 3개인 위의 생성자를 호출하여
매개변수 값에 차레로 값을 넣어줌
}
Car(String color){
this(color, "auto",4);
} // this 로 맨 위의 생성자를 호출하여 color 매개변수를 넣으면
color, auto,4로 나오게 함
public void showInfo() {
System.out.println("색상:"+ color);
System.out.println("gearType:"+ gearType);
System.out.println("문의 개수:"+ door+"\n");
}
}
public class ThisTest {
public static void main(String[] args) {
Car c1 = new Car();
c1.showInfo();
Car c2 = new Car("Black");
c2.showInfo();
Car c3 = new Car("Red","manual",2);
c3.showInfo();
}
}
▽
색상:white
gearType:auto
문의 개수:4
색상:Black
gearType:auto
문의 개수:4
색상:Red
gearType:manual
문의 개수:2
▶ super / super()
▷ super
- 부모클래스의 메서드를 자식클래스에서 오버라이딩한 경우에 super 을 사용함
- 부모클래스의 메서드 내용에 추가적으로 작업을 덧붙이는 경우라면
super 을 사용해서 부모클래스의 메서드를 포함시키는 것이 좋다
- 자식클래스 내부에서 부모클래스의 메서드를 사용하고싶다면 super 키워드 사용
//부모클래스 메서드
public void showInfo() {
System.out.println("이름:"+name);
System.out.println("나이:"+age);
}
//자식클래스 메서드
public void showInfo() {
super.showInfo(); //
System.out.println("전공:"+major);
}
// : super이용하여 중복제거 (showInfo 메서드 오버라이딩한거임)
= > 이름,나이,전공 출력 확인 가능
public String findLocation() {
return super.findLocation()+", z="+z; // 부모 메서드 호출
}
=> 이렇게 편리하게 사용가능 !
▷ super() - 부모 생성자를 호출하는 super()
class Parent{
int x=10;
}
class Child extends Parent{
int x=20;
public void method() {
System.out.println("x="+x); //20
System.out.println("this.x="+this.x); //20
System.out.println("super.x="+super.x); //10
}
}
public class SuperTest {
public static void main(String[] args) {
Child ch= new Child();
ch.method();
}
}
※ this와 super, this()/super() 를 비교하여 설명
자신의 멤버를 참조하는 this => this.멤버
생성자를 호출하는 this() => 같은 클래스의 다른 생성자를 호출할 때 사용한다.
부모의 멤버를 참조하는 super => super.멤버, 부모의 멤버와 자신의 멤버를 구별하는 데 사용된다
부모 생성자를 호출하는 super()
◈ 전화번호부 만들기 속 '검색하기' 기능
- 그냥 . . 통째로 외우자 . . !!!!
private int search(String name) {
int index = -1;
for (int i=0;i<count;i++) {
PhoneInfo info = p[i];
if(name.equals(info.getName()))
index = i;
}
return index;
}
search 기능은 delete 할때도 사용해야할 수 있으니까 따로 만들어둔다
= > int index 를 -1 로 초기화 한다
PhoneInfo 의 i 번째 배열을 info 변수에 저장한다
만약 ( info 배열에서 가져온 name 이 == 매개변수 name) 과 같다면
int index 의 값을 i 로 변경.
그렇지않으면 -1 로 유지.
나는 지금 내가 '검색' 했던 name 이 i 번째 배열에 존재한다는 것을 search를 통해 알게되었다
그럼 이제 검색한 이름을 포함하고있는 i 번째 배열의 값 ( name, num, birth ) 을 뽑아보자 !
public void searchData() {
System.out.println("데이터 검색을 시작합니다");
System.out.println("이름:");
String name = sc.nextLine();
int dataIndex = search(name);
if(dataIndex<0) {
System.out.println("해당하는 데이터가 존재하지 않습니다");
}else {
p[dataIndex].showPhoneInfo();
System.out.println("데이터 검색이 완료되었습니다");
}
}
위 search 에서 조회되지않아 처음 초기화 시켜놓았던 -1 값으로 유지되었다면
"해당하는 데이터가 존재하지 않습니다" 알림이 뜬다
i 번째 배열 순서를 int dataIndex 에 넣고
dataIndex 번째 ( =i번째 ) 배열의 전체 info 를 보여줘 라고 명령했다 ( p[dataIndex].showPhoneInfo(); )
내가 검색했던 'name' 이 포함된 배열의 전체값 (name , num, birth) 확인가능 !
'JAVA' 카테고리의 다른 글
<Eclipse 이클립스 단축키> (0) | 2022.03.01 |
---|---|
[JAVA] super() / final / 포함관계 (Has a) / 클래스를 멤버변수로 넣기 / classpath (0) | 2022.03.01 |
[JAVA] 클래스배열 (0) | 2022.02.24 |
[JAVA] Static (0) | 2022.02.23 |
[JAVA] 생성자 / 접근제한자 / getter,setter (0) | 2022.02.22 |