과제 풀이
https://laker99.tistory.com/23?category=1065834
System.out.printf("%.2f", l);
- 소숫점 둘째자리까지(%.2) 출력하고 실수형태(%f) 로 출력
DecimalFormat df = new DecimalFormat("0.00"); //내 코드
DecimalFormat df = new DecimalFormat("###.00"); //강사님 코드
- 0과 #은 의미가 다르다.
- ###을 넣으면 두자리여도 두자리만 표시하고 세자리면 세자리로 표시한다.
- 000을 넣으면 0은 무조건 자리를 채워넣는 형식, 31.42인 값이 031.42 로 표시된다.
상속을 쓰는 이유
- 중복코드를 줄이기 위해서
- 통일성있는 클래스를 설계하기 위해서
- 그래픽프로그램에서 상속을 많이 사용한다
- 나중에 JSP model2 = MVC 패턴개발 를 할때 클래스가 많을때 사용한다
자바에서 그래픽 프로그램
- CUI(Console User Interface)
- GUI(Graphic User Interface)
그래픽 프로그램 관련 패키지
- java.awt.*
- javax.swing.*
- javafx.*
- 여기 그래픽 프로그램 만들기 위한 클래스들이 모여있다
- 그래픽 프로그램에서 상속을 많이 사용함
- 캔버스, 체크박스, 프레임, 스크롤바, 메뉴, 텍스트필드 등 만들 수 있다
상속관련 용어 정리
- 부모클래스 = 상위클래스 = 슈퍼클래스
- 자식클래스 = 하위클래스 = 서브클래스 = 파생클래스
단일상속
- 자바는 단일상속만 가능
- 두개이상의 클래스로부터 상속받을수없다(C++, Python은 가능)
+ 부모클래스로 객체를 만드는게 의미없다(상속)
+ 자식클래스로 객체를 만드는게 의미있다(부모클래스의 필드와 메소드도 받았으므로)
패키지와 파일
- 한개 파일에 클래스 여러개 들어가도된다
- 나중에 컴파일될때 바이트코드는 클래스별로 따로따로 만들어짐
- 패키지는 폴더를 의미한다
상속 예제1
- SuperSub01.java
- 자식클래스명 옆에 extends 옆에 부모클래스명을 쓰자
package p2022_07_05;
class Parent {
public void parentPrn() { //부모 클래스
System.out.println("슈퍼 클래스 메서드는 상속된다.");
}
}
//Parent를 슈퍼 클래스로 하는 서브 클래스 Child 정의
class Child extends Parent { //자식 클래스
public void childPrn() {
System.out.println("서브 클래스 메서드는 슈퍼가 사용 못한다.");
}
}
//Parent를 슈퍼 클래스로 하는 서브 클래스 Child 정의
//Parent클래스의 parentPrn() 메소드는 자식 클래스에 상속된다.
class SuperSub01 {
public static void main(String[] args) {
Child c = new Child(); // 서브 클래스로 객체를 생성
c.parentPrn(); // 슈퍼 클래스에서 상속 받은 메서드 호출
c.childPrn(); // 서브 클래스 자기 자신의 메서드 호출
System.out.println("-------------------------------------->> ");
Parent p = new Parent(); // 슈퍼 클래스로 객체 생성
p.parentPrn(); // 슈퍼 클래스 자기 자신의 메서드 호출
// p.childPrn( ); //서브 클래스 메서드는 가져다 사용 못함
}
}
- 상속은 부모가 자식에게 일방적으로 주는것만 가능하다
- 부모클래스는 자식클래스의 멤버(필드나 메소드) 사용불가!
상속 예제2
- SuperSub04.java
package p2022_07_05;
class Point2D { // 부모 클래스
protected int x = 10; // private int x=10;
protected int y = 20; // private int y=20;
}
// 부모 클래스의 필드의 접근제어자가 private이면 자식이 접근할 수 없다.(상속 불가), 여기선 오류 발생
class Point3D extends Point2D { // 자식 클래스
protected int z = 30;
public void print() {
System.out.println(x + ", " + y + ", " + z);
}
}
class SuperSub04 {
public static void main(String[] args) {
Point3D pt = new Point3D();
pt.print();
}
}
- Point2D클래스가 부모클래스, 안의 필드 x, y 의 접근제한자가 protected
- Point3D클래스가 Point2D 클래스를 상속받음
- Point3D의 필드 protected int z, 메소드 print();
- 메인메소드가 있는 클래스 SuperSub04
- 메인메소드에서 Point3D 클래스로 객체를 생성하고 pt.print()로 메소드 호출
- 그럼 이 print()에서 x,y는 자기 클래스의 멤버는 아니지만 부모 클래스의 멤버이므로
자기거인것처럼 출력하는 것임
- 이때 접근 제어자, Point2D의 접근제어자를 private으로 두면? 오류발생, 자식 클래스에 상속 안된다!
- 부모클래스의 필드/메소드가 private이면 자식클래스라도 외부클래스이므로 접근불가, 상속을 못함
- private만 아니면 다 됨, default, public, protected는 다 상속 된다
접근제어자 protected
- 상속에선 나중에 접근제어자를 protected를 많이 씀
- 심지어 패키지가 달라져도 상속관계에 있을때는 자식이 접근 가능하다
패키지가 달라져도 접근가능한 경우
1. public인 경우
2. protected이고 상속관계인 경우 자식이 부모클래스 필드/메소드 접근
* 자바의 접근 제어자
1. 상속 관계가 있는 경우에 2개의 클래스(부모,자식 클래스)가 같은 패키지 안에 들어 있을때는 부모의 접근제어자가 default, protected, public 접근제어자인 경우에 자식클래스에서 접근 할수 있다. (단, private접근 제어자만 자식 클래스에서 접근 할 수 없음)
2. 상속 관계가 있는 경우에 2개의 클래스(부모,자식 클래스)가 다른 패키지 안에 들어 있을때는부모의 접근제어자가 protected, public 접근제어자인 경우에 자식클래스에서 접근 할수 있다.
3. 상속 관계가 없는 경우에 2개의 클래스가 서로 다른 패키지 않에 들어 있을때는 public 접근제어자로 되어 있어야만 다른 클래스에서 접근 할 수 있다.
+ 메소드 오버라이딩
- 상속에서 가장 중요한 개념
- 반드시 상속이 전제되어야만 쓸 수 있다.
- 메소드는 상속이 되지만, 부모로 부터 상속받은 메소드를 이름과 형식은 같게 하지만 안의 내용을 다르게 하는것
- 나중에 자세히 공부할것
상속 예제 3-1 (필드)
- SuperTest02.java
package p2022_07_05;
//부모 클래스 안에 있는 필드는 자식 클래스에게 상속된다.
class Point2D2 { //부모 클래스
protected int x = 10;
protected int y = 20;
}
class Point3D2 extends Point2D2 { //자식 클래스
protected int z = 30;
public void print() {
System.out.println(x + ", " + y + ", " + z); // x와 y는 상속 받아 사용하는 멤버변수
}
}
class SuperTest02 {
public static void main(String[] args) {
Point3D2 pt = new Point3D2();
pt.print();
}
}
+ protected이므로 상속 가능
- 이 예제는 필드 중복 그거 아니고 다음 예제이다
- 위 예제는 그냥 부모 클래스 안에 있는 필드는 자식 클래스에게 상속된다는걸 보여주는 예제
- 그럼 부모클래스에 있는 필드 x, y 를 상속받은 자식 클래스에서 똑같은 이름 x, y으로 필드를 정의해보자
- 자식클래스로 객체 만들어서 필드값출력할떄 어느값을 출력하는가?
-> 새로정의한 x, y값만 출력됨.
- 다음 예제에서 설명
상속 예제 3-2 (필드의 상속)
- SuperTest03.java
package p2022_07_05;
//부모 클래스에 있는 필드를 자식 클래스에서 재정의(동일한 이름의 변수)하면,
//자식 클래스에서 재 정의한 필드만 사용 가능하다.
class Point2D3 { //부모 클래스
protected int x = 10; // Point3D에서 다시 한번 정의되므로 은닉 변수가 됨
protected int y = 20; // 은닉 변수는 쉐도우 변수라고도 함
}
class Point3D3 extends Point2D3 { //자식 클래스
protected int x = 40; // 슈퍼 클래스에 존재하는 멤버변수를
protected int y = 50; // 서브 클래스에 다시 한 번 정의함
protected int z = 30;
public void print() {
System.out.println(x + ", " + y + ", " + z); // x와 y는 재 정의된 Point3D 클래스 소속
}
}
class SuperTest03 {
public static void main(String[] args) {
Point3D3 pt = new Point3D3();
pt.print();
}
}
40, 50, 30
- x, y가 중첩되고 있다
- 결론은 새로정의한 x, y값만 출력됨, 즉 10, 20 대신 40, 50 이 출력됨
- 기존에 상속해준 부모 클래스의 x, y 필드는 더이상 사용이 되지않음, 은닉이된다
-> 이 변수를 은닉 변수 = 쉐도우 변수 라고 함
- 이 은닉 변수들에 굳이 접근하고 싶으면 super. 을 사용해서 접근한다!
필드의 상속 정리
- 부모 클래스에 있는 필드를 자식 클래스에서 재정의(동일한 이름의 변수)하면, 자식 클래스에서 재정의한 필드만 사용 가능하다.
은닉 변수에 접근
- super.x, super.y 하면 은닉변수에 접근가능하다
- 쓸 일이 많지 않다
은닉 변수에 접근 예시
- 은닉변수에 굳이 접근하려면 super. 해서 접근
- 부모 클래스에 접근해서 값을 구해오라는 의미
- SuperTest04.java
package p2022_07_05;
//super : 부모 클래스를 의미함
//super.x 는 부모 클래스의 은닉된 필드를 호출할 때 사용된다.
//super.x 는 "자식클래스"의 "메소드 안"에서만 사용할 수 있다. (주의)
//그 외의 장소에서 System.out.println(super.x); //오류 발생
class Point2D4 { // 부모 클래스
protected int x = 10; // 은닉 변수
protected int y = 20; // 혹은 쉐도우 변수
}
class Point3D4 extends Point2D4 { // 자식 클래스
protected int x = 40; // 슈퍼 클래스에 존재하는 멤버변수를
protected int y = 50; // 서브 클래스에 다시 한 번 정의함
protected int z = 30;
// System.out.println(super.x); 메소드 내부가 아니므로 오류
public void print() {
System.out.println(x + ", " + y + ", " + z); // x와 y는 재 정의된 Point3D 클래스 소속
}
public void print02() {
System.out.println(super.x + ", " + super.y + ", " + z); // Point2D 클래스 소속 멤버변수로 접근
}
}
class SuperTest04 {
public static void main(String[] args) {
Point3D4 pt = new Point3D4();
pt.print(); // 40, 50, 30 // Point3D의 x, y
pt.print02(); // 10, 20, 30 // Point2D의 x, y
System.out.println(pt.x); // 40
}
}
40, 50, 30
10, 20, 30
40
은닉 변수에 접근 정리
- super : 부모 클래스를 의미함
- super.x 는 부모 클래스의 은닉된 필드를 호출할 때 사용된다.
- super.x 는 "자식클래스"의 "메소드 안"에서만 사용할 수 있다. (주의)
- 그 외의 장소에서 System.out.println(super.x); //오류 발생
super 와 this
- super : 부모 클래스를 의미하는 일종의 레퍼런스 변수
- this : 자기 클래스를 의미하는 일종의 레퍼런스 변수
* this와 super
this. : 생성자와 메소드에서 매개변수와 멤버변수 이름이 동일한 경우에 사용
this() : 같은 클래스내에 있는 다른 생성자를 호출(다른 클래스 내의 생성자는 이걸로 호출하지않음)
super. : 부모 클래스에 있는 은닉된 멤버변수와 메소드를 호출 할때 사용, 반드시 자식 클래스의 메소드 내에 써야만 사용가능하다. 자식 클래스의 메소드 밖이나 다른 클래스 내에서 사용불가
super() : 부모 클래스의 매개변수를 가진 생성자를 호출 할 때 사용
메소드로의 적용 (메소드 오버라이딩)
- 필드에서 재정의된 필드가 사용되는 것 처럼 메소드도 마찬가지이다.
- 메소드는 메소드 오버라이딩이라고 하지만 필드는 이런거 따로 부르는 이름이 없다
- 결론적으론 메소드도 새로 정의된 메소드 오버라이딩된 메소드만 호출됨
- 부모 클래스의 메소드는 은닉 메소드가 됨, 굳이 호출하고 싶으면 super.메소드() 로 호출하면된다
- 필드때처럼 부모의 메소드와 똑같은 이름 + 똑같은 형식 으로 메소드를 만들어야함
- 메소드 오버라이딩(Method Overriding), 동일이름 동일형식 다른내용 상속전제 필수
메소드 오버라이딩 예제
- SuperSub05.java
package p2022_07_05;
// 메소드 오버라이딩(Method Overriding)
// : 부모 클래스로부터 상속받은 메소드를 자식 클래스에서 재정의 해서 사용하는 것.
// 1. 부모 클래스로부터 상속받은 메소드를 자식 클래스에서 메소드 오버라이딩을 하면
// 메소드 오버라이딩 된 메소드만 호출되고, 부모 클래스의 메소드는 은닉이 되어서
// 자식클래스에 상속되지 않는다.
// 2. 부모 클래스에 은닉된 메소드를 호출할 때는 자식클래스의 메소드 안에서
// super.parentPrn() 형식으로 호출해야 된다.
class Parent05 { //부모 클래스
public void parentPrn() { //은닉 메소드가 된다
System.out.println("슈퍼 클래스 : ParentPrn 메서드");
}
}
//Parent05를 슈퍼 클래스로 하는 서브 클래스 Child05 정의
class Child05 extends Parent05 { //자식 클래스
// super.parentPrn(); //오류 발생, 자식클래스의 메소드 내부여야함
// 슈퍼 클래스에 있는 ParentPrn 메서드를 오버라이딩하면
// Child05로 선언된 객체는 슈퍼 클래스의 메서드가 은닉되어 상속 받지 못하게 된다.
public void parentPrn() { // 메소드 오버라이딩(Method Overriding), 동일이름 동일형식 다른내용 상속전제 필수
System.out.println("서브 클래스 : ParentPrn 메서드");
}
public void childPrn() { // 자식 클래스만 있는 메소드
super.parentPrn(); //부모 클래스의 은닉 메소드 호출
System.out.println("서브 클래스 : ChildPrn 메서드");
}
}
class SuperSub05 {
public static void main(String[] args) {
Child05 c = new Child05(); // 서브 클래스로 객체를 생성
c.parentPrn(); // 오버라이딩된 서브 클래스의 메서드 호출(새로 정의된, 오버라이딩된 메소드만 호출됨)
c.childPrn(); // 서브 클래스 자기 자신의 메서드 호출
System.out.println("-------------------------------------------->> ");
Parent05 p = new Parent05(); // 슈퍼 클래스로 객체를 생성
p.parentPrn(); // 슈퍼 클래스(자기 자신)의 메서드 호출
}
}
서브 클래스 : ParentPrn 메서드
슈퍼 클래스 : ParentPrn 메서드
서브 클래스 : ChildPrn 메서드
-------------------------------------------->>
슈퍼 클래스 : ParentPrn 메서드
- 은닉된 메소드도 호출할때는 super.메소드() 로 호출하면 호출된다!
- super.메소드() 를 쓰는 위치는 필드랑 동일하게 자식 클래스의 메소드 안에서 사용해야함 (주의)
ex) super.parentPrn();을 자식 클래스의 메소드 밖에서 쓰면 오류 발생함
- 메소드 오버라이딩을 하면 오버라이딩된 메소드만 호출된다.
- 부모클래스로부터 상속된 메소드는 사용이 더이상되지않고 은닉메소드가 된다
- 은닉메소드를 굳이 호출될때는 자식 클래스의 메소드 내에서 super.메소드() 로 호출
메소드 오버라이딩(Method Overriding) 정리
- 부모 클래스로부터 상속받은 메소드를 자식 클래스에서 재정의 해서 사용하는 것.
- 부모 클래스로부터 상속받은 메소드를 자식 클래스에서 메소드 오버라이딩을 하면 메소드 오버라이딩 된 메소드만 호출되고, 부모 클래스의 메소드는 은닉이 되어서 자식클래스에 상속되지 않는다.
- 부모 클래스에 은닉된 메소드를 호출할 때는 자식클래스의 메소드 안에서 super.parentPrn() 형식으로 호출해야 된다.
* 메소드 오버라이딩(Method Overriding)
- 부모 클래스로 부터 상속받은 메소드를 자식 클래스에서 재정의 해서 사용하는것
- Spring , JSP 할 때도 계속 따라가는 개념이므로 잘 익혀둬야 한다.
은닉 정리
- 결과적으로 자식 클래스에서 재정의 시 부모클래스안의 상속이 되는 필드, 메소드는 상속이 되지 않는다
- 은닉이 됨. 사용하려면 자식클래스의 메소드 안에서 super.필드명, super.메소드명() 으로 호출가능하다
+ 메소드 오버라이딩을 해도 되고 안해도 되지만 곧 배울 추상클래스, 인터페이스의 경우에는 반드시 메소드 오버라이딩을 해야하는 경우가 있다, 하지 않으면 오류 발생
+ 상속에서는 메소드와, 메소드 오버라이딩이 제일 중요하다
생성자와 상속
- 기본적으로 생성자는 상속되지 않는다, 어떻게 쓸까?
- 자식 클래스의 객체를 생성할때, 자식 클래스의 생성자가 호출되면 부모 클래스의 기본 생성자를 연쇄적으로 호출해줌
- 자식 클래스의 생성자는 기본생성자 여도 되고 매개변수를 가진 생성자여도 상관없음
- 이때 부모 클래스의 생성자는 "기본 생성자"만 호출되어 실행이됨
생성자와 상속 예제
- SuperTest05.java
package p2022_07_05;
class Point2D05 { //부모 클래스
protected int x = 10; //필드
protected int y = 20;
public Point2D05() { //부모클래스의 기본 생성자
System.out.println("슈퍼 클래스인 Point2D 생성자 호출");
}
}
class Point3D05 extends Point2D05 { //자식 클래스
protected int z = 30;
public void print() {
System.out.println(x + ", " + y + ", " + z);
}
public Point3D05() { //자식클래스의 기본 생성자
System.out.println("서브 클래스인 Point3D 생성자 호출");
}
}
class SuperTest05 {
public static void main(String[] args) {
Point3D05 pt = new Point3D05(); //자식클래스의 기본생성자 호출
pt.print();
슈퍼 클래스인 Point2D 생성자 호출
서브 클래스인 Point3D 생성자 호출
10, 20, 30
- 즉, main메소드에서 자식클래스의 생성자가 먼저 호출되었지만 실행 결과는 부모클래스의 기본 생성자의 출력문이 먼저 출력됨
- Point3D05 클래스의 기본 생성자가 호출되면 부모 클래스인 Point2D05 클래스의 기본 생성자를 호출함
- 그러므로 "슈퍼 클래스인 Point2D 생성자 호출" 출력 다음 "서브 클래스인 Point3D 생성자 호출" 메세지를 출력한다
- 부모 클래스의 기본생성자 만들어놓지 않으면 컴파일러가 자동으로 만듬
- 지금처럼 기본생성자 만들어뒀을때는 객체 생성할때 부모 클래스의 기본 생성자를 호출함
생성자와 상속 정리
* 상속에서의 생성자
1. 생성자는 기본적으로 상속이 되지 않는다
2. 자식클래스를 이용해서 객체를 생성할때 자식클래스의 생성자(기본생성자,매개변수 있는 생성자 모두 가능)가 호출되면, 부모클래스의 기본생성자가 자동으로 호출된다.
3. 매개변수가 있는 생성자가 있는 경우에는 더이상 컴파일러가 기본 생성자를 자동으로 생성해 주지 않는다.
4. 부모 클래스의 매개변수가 있는 생성자를 자식 클래스에서 호출 할때는 super()를 이용해서 호출할 수 있다. 단, super()는 자식 클래스의 생성자 안에서만 사용 가능함.
부모클래스의 기본생성자 호출
- 심지어 부모 클래스 쪽에 기본생성자가 없어도 된다.
- 자식생성자가 부모 클래스의 기본생성자를 만들어서 호출해줌
- 또한 자식 클래스 쪽에 기본생성자가 없어도 된다, 컴파일러가 자동으로 기본클래스를 생성 후 부모 클래스의 기본 생성자 호출
- 만약 부모 클래스의 기본생성자가 아닌 매개변수가 있는 생성자를 호출하고 싶다면, super()로 명시적으로 호출해줘야지만 부모클래스의 매개변수가 있는 생성자를 호출 할 수 있다
- 자식클래스는 매개변수 있는 상속자여도 된다
public Point3D05(int a) { //자식클래스의 기본 생성자
System.out.println("서브 클래스인 Point3D 생성자 호출");
}
// main
Point3D05 pt = new Point3D05(30); //자식클래스의 기본생성자 호출
- 이어도 문제 없고 부모클래스의 기본생성자를 호출함 또한
public Point3D05() { //자식클래스의 기본 생성자
System.out.println("서브 클래스인 Point3D 생성자 호출");
}
- 이 코드(자식클래스의 기본생성자) 를 주석으로 막아도 컴파일러가 자동으로 기본클래스를 생성
- 또한 연쇄적으로 부모클래스의 기본 생성자도 호출됨
부모클래스의 기본생성자 호출 정리
- 자식클래스는 기본생성자여도 되고 매개변수가 있는 생성자여도 됨
- 부모클래스는 기본생성자만 연쇄적으로 자동적으로 호출해주게 되고, 매개변수가 있는 생성자는 우리가 super()로 명시해서 직접 호출해 줘야함
부모클래스에 기본생성자가 없다면
- 부모클래스에서 이미 매개변수가 있는 생성자가 있는경우 기본생성자가 자동으로 만들어지지 않는다
- 그래서 기본생성자를 내가 명시해서 만들어주지 않으면 자식클래스의 생성자에도 오류가 생김
부모클래스에 기본생성자가 없다면 예제/super() 통해서 호출하는 예제
- SuperTest06.java
- 이 예제에선 부모클래스에서 이미 매개변수가 있는 생성자가 있으므로 기본생성자가 만들어지지 않는다
-> 그래서 기본생성자를 내가 명시해서 만들어주지 않으면 자식클래스의 생성자에도 오류가 생김
public Point2D06( ){ System.out.println("슈퍼 클래스인 Point2D 생성자 호출"); }
- 부모 클래스의 기본 생성자 주석을 풀어야만 자식클래스에서 오류가 생기지 않음
- 부모의 기본생성자를 자식 객체 생성될때 연쇄호출됨
- 부모 클래스에서 매개변수가 있는 생성자는 자식 클래스의 생성자에서 호출해주지 않는다, super() 로 호출해야함
- 그리고 부모 클래스에서 매개변수가 있는 생성자가 있고 기본 생성자가 적혀져있지 않으면 기본생성자는 자동으로 만들어지지 않는다
- 이런 경우에는 기본생성자를 명시해주지 않으면 자식 생성자쪽에서 오류가 남.
+ 매개변수가 있는 생성자가 있을때는 예외적으로 컴파일러가 기본생성자를 생성해주지 않는다.
- 물론 자식 클래스에서 호출하지 않을때는 안만들어도 되지만 자식 클래스 쪽에서 호출을 할떄는 부모클래스의 기본생성자가 필요하고, 부모 클래스의 기본생성자 없으면 오류남
- 지금은 자식 클래스의 생성자가 호출되므로 부모 클래스의 기본 생성자도 호출되기때문에 부모클래스의 기본 생성자가 필요하다
부모클래스의 매개변수가 있는 생성자 호출하는 방법
- 자식클래스에서 super() 형태로 호출해야함
- super()는 자식클래스의 생성자 내부 첫번째 라인에 써야함! 위치가 정해져있다
package p2022_07_05;
//super()
//1. super()는 부모 클래스의 매개변수를 가진 생성자를 호출할 때 사용한다.
//2. super()는 자식 클래스의 생성자 안에서 첫번째 라인에 사용해야 한다.
//3. super()를 이용해서 부모 클래스의 매개변수를 가진 생성자를 호출하면,
//더이상 부모클래스의 기본생성자를 호출해주지 않는다.
class Point2D06 { // 부모 클래스
protected int x = 10; // 필드
protected int y = 20;
// 매개변수가 있는 생성자가 있을때는 예외적으로 컴파일러가 기본생성자를 생성해주지 않는다.
public Point2D06() { //기본 생성자
System.out.println("슈퍼 클래스인 Point2D 생성자 호출");
}
public Point2D06(int xx, int yy) {
x = xx;
y = yy;
}
}
class Point3D06 extends Point2D06 { //자식 클래스
protected int z = 30;
public void print() {
System.out.println(x + ", " + y + ", " + z); //상속받은 필드 x, y
}
public Point3D06() { //자식 클래스의 기본 생성자
super(50,60); // 부모 클래스의 매개변수가 있는 생성자 호출
System.out.println("서브 클래스인 Point3D 생성자 호출");
}
}
class SuperTest06 {
public static void main(String[] args) {
Point3D06 pt = new Point3D06(); //자식 클래스의 생성자 호출
pt.print();
}
}
서브 클래스인 Point3D 생성자 호출
50, 60, 30
- 부모클래스의 매개변수 2개인 생성자가 호출되면서 x값이 50, y값이 60이 되는 것이다.
위 예제 처리과정
1. 메인메소드에서 먼저 Point3D06이란 자식클래스의 생성자를 호출한다
2. 자식클래스의 생성자가 호출됨, 내부 코드를 실행함
3. 원래는 자식클래스의 생성자가 호출되면 연쇄적으로 부모클래스의 기본 생성자를 호출함
4. 근데 여기선 super()를 썼으므로 super()가 우선이 됨
- super()를 통해 호출된 부모클래스의 매개변수있는 생성자가 호출되면 부모클래스의 기본생성자는 호출되지 않음
5. 그래서 "슈퍼 클래스인 Point2D 생성자 호출" 은 출력되지 않았고 값은 50, 60으로 변경됨
- 즉 매개변수를 가진생성자만 호출되었다는 의미
Point2D06 (부모)클래스의 매개변수 2개인 생성자를 호출하고 싶다면? (위 예제 부분1)
public Point2D06(int xx, int yy) {
x = xx;
y = yy;
}
- 이걸 호출하고 싶으면 자식클래스의 생성자 내부
public Point3D06() { //자식 클래스의 기본 생성자
super(50,60);
System.out.println("서브 클래스인 Point3D 생성자 호출");
}
- 에서 super()를 통해서 부모 클래스의 매개변수가 2개인 생성자를 호출한다
- 부모 클래스의 기본생성자 주석으로 막아도 오류 안생김
super() 유의사항
- super()는 자식클래스의 생성자 안에서만 사용가능하다
- 생성자 내부의 첫번째 라인만 가능하다! 다른 장소에 들어가면 오류 발생한다
- 자식 생성자가 호출되면 부모의 기본생성자가 호출되지만 자식 생성자 내에서 super()를 써서 매개변수 있는 생성자 호출할떄는
부모의 기본생성자는 호출되지 않는다.
- super()가 우선순위 높다, super()쓰면 기본생성자 호출안해줌
- 동시에 2개(기본 생성자, 매개변수가 있는 생성자) 호출해주지 않는다
- super()는 메소드 안에 못쓴다.
- super()가 우선순위 높다, super()쓰면 기본생성자 호출안해줌
super() 정리
1. super()는 부모 클래스의 매개변수를 가진 생성자를 호출할 때 사용한다.
2. super()는 자식 클래스의 생성자 안에서 첫번째 라인에 사용해야 한다.
3. super()를 이용해서 부모 클래스의 매개변수를 가진 생성자를 호출하면, 더이상 부모클래스의 기본생성자를 호출해주지 않는다.
super. 와 super()의 차이
- super. : 메소드 오버라이딩 되었을때 부모클래스 안의 필드, 메소드를 호출할 때 사용, 잘 안 쓴다
- super() : 자식클래스에서 부모 클래스의 매개변수를 가진 생성자를 호출할 때 사용, 잘 쓴다
+ super() 는 그래픽 프로그램 예제 다룰 때 썼었다
- FrameTestEx extends Frame 클래스의 생성자 첫번째 라인에서 super("Frame Test"); 라고 썼다.
- 자기 부모의 매개변수가 있는 생성자를 호출하라는 의미로서 부모인 Frame클래스의 매개변수가 String인 생성자를 호출하고 있다
this. 예제
- DMBCellPhone.java
package p2022_07_05;
// p290 ~ 292
class CellPhone{ // 부모 클래스
String model; // 필드
String color;
void powerOn() { // 메소드
System.out.println("전원을 켭니다.");
}
void powerOff() {
System.out.println("전원을 끕니다.");
}
void bell() {
System.out.println("벨이 울립니다.");
}
void sendVoice(String message) {
System.out.println("자기:"+message);
}
void receiveVoice(String message) {
System.out.println("상대방:"+message);
}
void hangUp() {
System.out.println("전화를 끊습니다.");
}
}
// 부모 클래스의 필드와 메소드는 상속된다.
class DMBCellPhone extends CellPhone{ // 자식 클래스
int channel;
public DMBCellPhone(String model, String color, int channel) {
this.model = model; // 자바폰
this.color = color; // 검정
this.channel = channel; // 10
}
void turnOnDmb() {
System.out.println("채널:"+channel+"전 DMB방송 수신을 시작 합니다.");
}
void changeChannelDmb(int channel) {
this.channel = channel;
System.out.println("채널"+channel+"번으로 바꿉니다.");
}
void turnOffDmb() {
System.out.println("DMB방송 수신을 멈춥니다.");
}
}
public class DMBCellPhoneEx {
public static void main(String[] args) {
// TODO Auto-generated method stub
DMBCellPhone dmb = new DMBCellPhone("자바폰", "검정", 10);
// model, color 필드는 부모 클래스로 부터 상속 받아서 사용
System.out.println("모델:"+dmb.model);
System.out.println("색상:"+dmb.color);
System.out.println("채널:"+dmb.channel);
// 부모 클래스로 부터 상속 받아서 사용되는 메소드
dmb.powerOn();
dmb.bell();
dmb.sendVoice("여보세요");
dmb.receiveVoice("안녕 하세요! 저는 홍길동 입니다.");
dmb.sendVoice("아~ 예 반갑습니다.");
dmb.turnOnDmb();
dmb.changeChannelDmb(12);
dmb.turnOffDmb();
}
}
위 예제 부분 1
DMBCellPhone dmb = new DMBCellPhone("자바폰", "검정", 10);
위 예제 부분 2
public DMBCellPhone(String model, String color, int channel) {
this.model = model; // 자바폰
this.color = color; // 검정
this.channel = channel; // 10
}
- DmbCellPhone 클래스의 생성자에서 초기화할때 상속받은 필드들도 다 초기화하고 있다
- this. 써서 가능 model과 color는 상속을 받아 쓰는것
위 예제 부분 3
void changeChannelDmb(int channel) {
this.channel = channel;
System.out.println("채널"+channel+"번으로 바꿉니다.");
}
- DmbCellPhone 클래스의 메소드인 changeChannelDmb()에서 매개변수와 필드가 이름이 같기때문에 여기서도 this. 를 쓴다
위 예제 부분 4
// 부모 클래스로 부터 상속 받아서 사용되는 메소드
dmb.powerOn();
dmb.bell();
dmb.sendVoice("여보세요");
dmb.receiveVoice("안녕 하세요! 저는 홍길동 입니다.");
dmb.sendVoice("아~ 예 반갑습니다.");
- 상속받은 메소드를 자기것처럼 씀
+ Ctrl키 누르고 메소드명 클릭하면 그게 정의되어있는 곳으로 감! 파일 달라도 거기로 찾아감
메소드 오버라라이딩 예제
- ComputerEx.java
package p2022_07_05;
// p296 ~ 297
// 메소드 오버라이딩(Method Overriding)
// : 부모 클래스로 상속받은 메소드를 자식 클래스에서 재정의 해서 사용하는 것
class Calculator{ // 부모 클래스
double areaCircle(double r) {
System.out.println("Calculator 객체의 areaCircle() 실행");
return 3.14159 * r * r;
}
}
class Computer extends Calculator{ // 자식 클래스
@Override
double areaCircle(double r) { // 메소드 오버라이딩
// super.areaCircle(r);
System.out.println("Computer 객체의 areaCircle() 실행");
// TODO Auto-generated method stub
return Math.PI * r * r;
}
}
public class ComputerEx {
public static void main(String[] args) {
// TODO Auto-generated method stub
int r = 10;
Calculator cal = new Calculator();
System.out.println("원의 면적:"+ cal.areaCircle(r));
// 자식클래스에서 메소드 오버라이딩 된 메소드만 호출된다.
Computer comp = new Computer();
System.out.println("원의 면적:"+ comp.areaCircle(r));
}
}
- 부모클래스로부터 상속받은 Computer 클래스는 메소드 오버라이딩을 수행한다.
- 이때, 부모클래스의 이름과 형식 (매개변수, 리턴형) 그대로 해야한다
- 만약 부모클래스의 메소드를 호출하고 싶다면 return super.areCircle(r)로 super. 를 쓰면 된다.
- 클래스를 상속받을땐 메소드 오버라이딩을 해도 되고 안해도 됨.
- 상속을 하더라도 메소드 오버라이딩 안해도 됨
- 이게 끝나면 추상클래스라는걸공부하는데 추상클래스가 extends뒤에 오게되면 반드시 메소드 오버라이딩을 해야함
+ 인터페이스는 클래스처럼 extends로 상속받는게 아니라 implements 키워드로 상속을 받음
+ 직접 내가 클래스를 만들때 상속을 하려면 ex까지 쓰고 ctrl+ space하면 자동으로 입력됨
이클립스 메소드 오버라이딩 생성
- 이때 이클립스를 이용하면 메소드 오버라이딩 자동으로 만들어주는 기능 있다
- 주석으로 막고 이클립스로 메소드 오버라이딩 해보자
오른쪽 마우스 -> Source -> Override/Implement Methods
- 부모클래스, 조상클래스(Object등)가 보이고 그 안의 오버라이딩 할 메소드 선택 가능
- 원하는 메소드만 클릭해서 오버라이딩 하면 된다
- 그럼 이게 생성된다
@Override
double areaCircle(double r) {
// TODO Auto-generated method stub
return super.areaCircle(r);
}
오버라이드 어노테이션
@Override
- 컴파일러가 이 어노테이션 만나면 아래쪽에 메서드가 오버라이딩 잘 되었는지 체크한다
- 이런역할을 어노테이션이 해줌
- 없어도 실행에 지장은 없다.
메소드 오버라이딩 정리
- 오버라이딩 하면 부모클래스의 메소드가 아닌 자식클래스에서 메소드 오버라이딩 된 메소드만 호출된다.
- 은닉된 메소드를 굳이 호출할떄는 자식 클래스의 메소드에서 super. 으로 호출한다
- 이 내용이 그 다음의 추상클래스, 인터페이스와 연결됨 거기선 반드시 메소드 오버라이딩을 해야함
final 키워드
- 상속을 배우기 전 간단히 설명 했었다
- final 필드 : 수정 불가 필드 = 상수
- final 메소드 : 자식 클래스에서의 이 메소드 오버라이딩을 허용하지 않음 (마지막 메소드)
- final 클래스 : 상속을 허용하지 않는 클래스 (마지막 클래스)
- 여기서 final 메소드와 final 클래스를 볼 것
final 메소드
- 상속이 되더라도 메소드 오버라이딩 불가능 메소드 오버라이딩 하려하면 오류 발생시킴
final 클래스
- 해당 클래스를 상속 하려고 하면 오류 발생시킴
상속에서의 접근제어자
* 자바의 접근 제어자
1. 상속 관계가 있는 경우
1-1. 2개의 클래스(부모,자식 클래스)가 같은 패키지 안에 들어 있을때
- 부모의 접근제어자가 default, protected, public 접근제어자인 경우에 자식클래스에서 접근 할수 있다.
- (단, private 접근제어자만 자식 클래스에서 접근 할 수 없음)
1-2. 2개의 클래스(부모,자식 클래스)가 다른 패키지 안에 들어 있을때
- 부모의 접근제어자가 protected, public 접근제어자인 경우에 자식클래스에서 접근 할수 있다.
2. 상속 관계가 없는 경우
- 2개의 클래스가 서로 다른 패키지 안에 들어 있을때는 public 접근제어자로 되어 있어야만 다른 클래스에서 접근 할 수 있다.
import 기준
- 패키지가 달라질때 -> 반드시 import
패키지가 다를때 접근하는법
1. 접근제어자가 public 이면 다 됨
2. 두 클래스 상속관계 && 접근제어자 protected
+ 그래서 이 protected 접근제어자는 상속에서 많이 씀
상속과 접근제어자
1. 같은 패키지 안의 클래스 2개가 부모-자식 상속관계 -> private 빼고 다 접근가능하다
- public은 다 되고, default 는 원래부터 같은 패키지면 접근가능하고
- protected는 원래부터 같은 패키지면 접근 가능했고 또 상속관계면 다 접근 가능하기떄문에 접근 가능
2. 다른 패키지 안의 부모-자식 상속관계 -> protected, public 둘 중 하나여야만 함
- default 는 다른패키지는 접근 불가
- protected는 패키지가 달라져도 상속관계면 접근 가능함
- private은 자식 클래스라도 외부클래스이므로 접근 불가
+ private은 딱 자기 클래스만 접근 가능
- 다른 패키지더라도 상속관계이고 protected면 접근 가능하다
상속과 접근제어자 예제
- 예제 중에서 부모클래스는 src - packTest - packOne - AccessTest.java(부모클래스)
- 자식클래스 패키지 없기때문에 복사를 해서 바로 scr에 집어넣기, SubOne.java
- 제3의 클래스 SuperSubA.java
- 부모클래스 AccessTest.java는 scr의 packTest.packOne 패키지를 만들어서 넣기
- 자식 클래스는 default package안에 들어가게됨
- 부모클래스에는 4개의 변수가 있는데 접근제어자가 다 다르다
- 원래는 public 일떄만 다른 패키지 접근 가능하지만
- 상속관계에 있고 protected 면 접근 가능하다
- 즉 부모와 자식이 서로 다른 패키지 안에 들어가있을때 4가지 접근제어자 중 어떤 접근제어자가 접근가능하게하는지 알아보는 예제임
정리
- 부모클래스 (AccessTest) -> 여기 필드값에 다양한 접근제어자가 있다
- 자식 클래스(SubOne)는 다른 패키지 안에 있을떄 protected, public이 가능함
- 제3의 클래스(SuperSubA)는 public 클래스만 접근 가능
// 부모 클래스
package packTest.packOne;
public class AccessTest { //다른 패키지에서 가져다 사용할 것임으로 pubic으로
private int a=10; //[1] private
int b=20; //[2] 기본 접근 지정자
protected int c=30; //[3] protected
public int d=40; //[4] public
public void print( ){
System.out.println("AccessTest의 print");
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
// 자식 클래스
import packTest.packOne.AccessTest;
//AccessTest의 서브 클래스로 SubOne을 설계
class SubOne extends AccessTest {
void subPrn( ){
System.out.println(a); //[1. Sub] private -X 에러
System.out.println(b); //[2. Sub] 기본 접근 지정자-X 에러
System.out.println(c); //[3. Sub] protected -O
System.out.println(d); //[4. Sub] public -0
}
}
// 제 3의 클래스
//AccessTest랑 상속관계가 없는 클래스
class SuperSubA{
public static void main(String[] args){
AccessTest at=new AccessTest( );
at.print( );
System.out.println("main");
System.out.println(at.a); //[1. main] private -X 에러
System.out.println(at.b); //[2. main] 기본 접근 지정자-X 에러
System.out.println(at.c); //[3. main] protected -X 에러
System.out.println(at.d); //[4. main] public -O
}
}
1. 상속 관계 있는 자식클래스 SubOne 에선 부모 클래스와 자식 클래스가 서로 다른 패키지에 있을때
- 이때 private 접근제어자로 되어있는 a는 자식이더라도 상속이 안됨(접근이 안됨)
- 이때 default 접근제어자로 되어있는 b는 자식이더라도 상속이 안됨(접근이 안됨)
- 이때 protected 접근제어자로 되어있는 c는 자식이라서 상속이 됨(접근 가능)
- 이때 public 접근제어자로 되어있는 d는 public이니까 상속이 됨(접근 가능)
2. 상속 관계 없는 제3의 클래스 SuperSubA 에선 제3의 클래스인데 서로 다른 패키지에 있을때
- 기존 내용처럼 public 접근제어자로 되어있는 필드만 접근 가능\
강사님 정리
src - packTest - packOne - AccessTest.java(부모클래스)
SubOne.java(자식클래스) : protected, public만 접근가능
SuperSubA.java(제3의 클래스) : public만 접근가능
- 필드의 접근제어자를 주로 protected를 많이 씀
- 두 패키지가 상속관계 && 서로다른 패키지 -> public, protected 접근 가능
- public > protected > default > private
레퍼런스 형변환
- 추상클래스, 인터페이스까지 공부 후 공부
자바 3가지 자료형변환
1. 기본자료형 변환
2. Wrapper클래스로 주로 String <-> int 형 변환
3. 레퍼런스 형변환(반드시 두 클래스 사이 상속관계 있어야만 가능함)
추상클래스 개념 1 (개념과 특징)
- 이름만 있고 내용이 없는 클래스
- 자체적으로 객체를 생성할 수 없는 클래스
- 여태껏 한개의 클래스로 무한개 객체만들어냈지만 추상클래스는 객체 생성 불가
추상클래스 개념 2 (형식과 구성)
- 추상클래스는 일반 클래스와 구분하기 위해서 클래스 앞에 abstract를 붙임
- 추상메소드 앞에도 반드시 abstract 붙이고 맨뒤 세미콜론 ex) abstract void Method01();
- 추상클래스에 들어가는 멤버 : 일반 멤버변수, 추상 메소드, 일반 메소드 등 있다.
- 일반 클래스와 가장 큰 차이는 추상메소드를 가질 수 있다는 점
- 추상메소드를 가질 수 있다는게 가장 큰 특징
+ 추상메소드는 이름만있고 내용이 없는 메소드
추상클래스 개념 3 (생성과 사용)
- 추상클래스 상속 받을때는 클래스기떄문에 자식들은 일반 클래스 상속처럼 extends로 상속
- 그리고 부모 추상 클래스 나머지 안에 있는 추상메소드들을 반드시 메소드 오버라이딩 해야함
- 자체적으로 new연산자로 객체 생성 불가능한게 추상클래스 특징
- 부모 추상 메소드 : 공통적인 내용들을 넣어야함
ex) 새 클래스, 곤충 클래스, 물고기 클래스 -> 공통특징 추출해서 부모클래스 만듬 -> 부모클래스는 동물클래스
+ 나중에는 부모클래스 만들때 일반클래스보다 추상클래스를 부모클래스로 많이 만듬
추상클래스 개념 4 (상속)
- 자체적으로 객체 생성 안되므로 추상 클래스를 일반 클래스가 상속받아서 쓰는거다.
- 추상클래스를 상속받은 일반 클래스는 추상클래스 안에 들어있는 추상 클래스를 반드시 Method Overriding을해야한다
- 부모클래스의 이름, 형식 그대로 따라서 내용을 다르게 써내려가면 된다
- 메소드 오버라이딩 안하면 오류발생
- 추상클래스도 단일상속만 가능하다,2개이상의 추상클래스 상속 불가
- 자바는 일반클래스든 추상클래스든 다중상속 허용안하기 때문임
인터페이스
+ 추상클래스의 기능 있음 (추상메소드 가질수있음)
+ 인터페이스는 다중상속까지 허용함
+ 나중엔 추상클래스는 거의 안쓰고 인터페이스를 쓴다
+ 인터페이스 쓰기위해서 추상클래스 이해하는것임
+ 보통 추상클래스를 부모로 만드는게 아니라 인터페이스를 부모로 만듬
'국비지원 과정 > JAVA' 카테고리의 다른 글
코딩 10일 / 2022.07.04 / JAVA의 Wrapper 클래스, 박싱, 언박싱, 업캐스팅, 다운캐스팅, 상속1 (0) | 2022.07.12 |
---|---|
코딩 9일 / 2022.07.01 / JAVA의 문자열 처리 클래스(String, StringBuffer, StringTokenizer) (0) | 2022.07.11 |
코딩 8일 / 2022.06.30 / JAVA의 싱글톤, final, 날짜시간 관련 클래스 (0) | 2022.07.07 |
코딩 7일 / 2022.06.29 / JAVA의 접근제어자,메소드 오버로딩,정적 변수,정적 메소드 (0) | 2022.07.05 |
코딩 6일 / 2022.06.28 / JAVA의 클래스,객체,필드,생성자 (0) | 2022.07.01 |