1차시 메서드 오버라이딩
메서드 오버라이딩
: 상속을 통해 부모 클래스로부터 물려받은 메서드를 자식 클래스에 맞도록 수정하는 것
메서드 오버라이딩 규칙
1. 부모 클래스의 메서드와 동일한 시그니처를 사용, 반환 타입까지 동일해야 한다.
- 메서드 오버로딩과 헷갈리지 않기!! 메서드 오버로딩에서는 반환 타입이 중요하지 않다.
- 메서드 오버라이딩이 메서드 오버로딩보다 규칙이 더 강력하다.
2. 부모 클래스의 메서드보다 접근 범위를 더 좁게 수정할 수 있다.
- 하지만 대체적으로 접근 범위를 동일하게 한다.
3. 추가적인 예외가 발생할 수 있음을 나타낼 수 없다.
메서드 오버라이딩 불가 - 상속 관계가 불가능해서 메서드 오버라이딩도 불가능하다!
1. private 메서드: 부모 클래스 전용이므로 자식 클래스에 상속되지 않는다.
2. 정적 메서드: 클래스 소속이므로 자식 클래스에 상속되지 않는다.
3. final 메서드: final 메서드는 더이상 수정 불가능하므로 자식 클래스가 오버라이딩할 수 없다.
메서드 오버라이딩을 하면 컴파일러는 자식 클래스를 우선시해서 실행한다!
- 자식 클래스가 메서드를 오버라이딩하면 자식 객체는 부모 클래스의 오버라이딩된 메서드를 숨긴다.
(= 메서드의 우선순위가 바뀐다.)
package sec03; //같은 패키지 내의 3개의 자바 파일 Circle.java Ball.java InheritanceDemo.java
public class Circle { //부모 클래스 Circle
private void secret() {
System.out.println("비밀이다.");
}
protected void findRadius() {
System.out.println("반지름이 10.0센티이다.");
}
public void findArea() {
System.out.println("면적은 (π*반지름*반지름)이다.");
}
}
package sec03;
public class Ball extends Circle { //자식 클래스 Ball
private String color; //Ball 클래스에 추가한 필드
public Ball(String color) { //Ball 클래스에 추가한 생성자
this.color = color;
}
public void findColor() { //Ball 클래스에 추가한 메서드
System.out.println(color + " 공이다.");
}
public void findArea() { //메서드 오버라이딩 //오버라이드한 findArea()
System.out.println("넓이는 4*(π*반지름*반지름)이다.");
//상속받은 findArea()를 Ball 클래스에 맞게 수정
}
public void findVolume() { //Ball 클래스에 추가한 메서드
System.out.println("부피는 4/3*(π*반지름*반지름*반지름)이다.");
}
}
package sec03;
public class InheritanceDemo {
public static void main(String[] args) {
Circle c1 = new Circle(); //Circle 클래스로 c1 객체 생성
Ball c2 = new Ball("빨간색"); //Ball 클래스로 c2 객체 생성
System.out.println("원 :");
c1.findRadius();
c1.findArea();
//여기서 findArea()는 Circle 클래스의 findArea() 실행
System.out.println("\n공 :");
c2.findRadius();
c2.findColor();
c2.findArea();
//여기서 findArea()는 메서드 오버라이딩을 한 후기 때문에 실행 시 Ball 클래스의 findArea()가 실행됨
c2.findVolume();
}
}
부모 클래스의 멤버 접근
- 자식 클래스가 메서드를 오버라이딩해서 자식 객체에서 숨겨진 부모 클래스의 오버라이딩된 메서드는 super 키워드를 사용해서 호출
- super는 현재 객체에서 부모 클래스의 참조를 의미
package sec03.spr;
public class Circle { //부모 클래스 Circle
private void secret() {
System.out.println("비밀이다.");
}
protected void findRadius() {
System.out.println("반지름이 10.0센티이다.");
}
public void findArea() {
System.out.println("면적은 (π*반지름*반지름)이다.");
}
}
package sec03.spr;
public class Ball extends Circle { //자식 클래스 Ball
private String color;
public Ball(String color) {
this.color = color;
}
public void findColor() {
System.out.println(color + " 공이다.");
}
//메서드 오버라이딩한 findArea()
public void findArea() {
findRadius();
super.findArea(); //부모 메서드(Circle 클래스의 메서드) 실행
// super.secret(); //secret()은 private이라 오류 발생
System.out.println("넓이는 4*(π*반지름*반지름)이다.");
}
public void findVolume() {
System.out.println("부피는 4/3*(π*반지름*반지름*반지름)이다.");
}
}
메서드 오버라이딩과 메서드 오버로딩 비교
2차시 패키지와 부모 생성자
패키지
: 파일 시스템의 폴더를 이용하며 클래스 파일을 묶어서 관리하기 위한 수단
패키지에 의한 장점
- 패키지마다 별도의 이름 공간(Namespace)이 생기기 때문에 클래스 이름의 유일성 보장
- 클래스를 패키지 단위로도 제어할 수 있기 때문에 좀 더 세밀하게 접근 제어
대표적인 패키지
- java.lang 패키지: import 문을 선언하지 않아도 자동으로 임포트되는 자바의 기본 클래스를 모아둔 것
- java.awt 패키지: 그래픽 프로그래밍에 관련된 클래스를 모아둔 것
- java.io 패키지: 입출력과 관련된 클래스를 모아둔 것
패키지의 선언
- 패키지는 주석문을 제외하고 반드시 첫 행에 위치
- 패키지 이름은 모두 소문자로 명명하는 것이 관례
- 일반적으로 패키지 이름이 중복되지 않도록 회사의 도메인 이름을 역순으로 사용
package com.hankuk.people;
//.을 사용해서 각각의 정보를 활용
//이 패키지의 경우 파일 위치를 확인하면 (작업 위치) > com > hankuk > people
- 패키지의 이름을 설정하지 않을 시 default package
패키지의 사용
- 다른 패키지에 있는 공개된 클래스를 사용하려면 패키지 경로를 컴파일러에게 알려줘야 한다.
1. 패키지의 이름을 접두어로 사용하는 방법
- 패키지 이름이 짧거나 한두 번 사용할 시엔 괜찮으나 그렇지 않을 경우엔 전체 코드가 지저분해진다.
2. impor문을 이용하는 방법
- import 문: 패키지의 경로를 미리 컴파일러에게 알려주는 문장
- import 문은 소스 파일에서 package 문과 첫 번째 클래스 선언부 사이에 위치
/* impot 문 사용 방법 */
import 패키지이름.클래스;
import 패키지이름.*;
/* import 문 사용 예시 */
import com.hankuk.*; //com.hankuk 패키지에 포함된 모든 클래스
import com.hankuk.people.*; //com.hankuk.people 패키지에 포함된 모든 클래스
- 정적 import 문: 패키지 단위로 임포트하지 않고 패키지 경로와 정적 메서드를 함께 임포트
import static java.util.Arrays.sort; //정적 import 문
import java.util.Calender; //import 문
public class StaticImportDemo {
public static void main(Strings[] args) {
int[] data = { 0, 8, 0, 2 };
/* 정적 import 문이 있어서 클래스 이름 없이 다른 패키지에 있는 공개된 클래스의 멤버 사용 */
sort(data);
/* improt 문일 때는 클래스 이름과 함께 필드 사용 */
System.out.println(Calendar.JANUARY); //JANUARY는 상수
/* improt 문일 때는 클래스 이름과 함께 메서드 사용 */
Calendar.getInstance();
자식 클래스와 부모 생성자
- 자식 생성자를 호출하면 부모 생성자도 자동으로 호출
- 자식 생성자는 첫 행에 부모 생성자 호출 코드 super()가 있다. (super() 생성자 호출은 맨 먼저 해야 한다!)
class Box { //부모 클래스
public Box() {
...
}
}
class ColoredBox extends Box { //자식 클래스
public ColoredBox() { //자식 클래스의 생성자
/* (2) 부모 클래스의 생성자 호출 */
super(); //부모 생성자 호출 //무조건 첫 행에!
/* (3) 부모 클래스의 생성자를 마치고, 자식 클래스의 생성자로 돌아옴 */
}
}
public class BoxDemo { //메인 메서드 갖는 클래스
public static void main(Strings[] args) {
/* (1) 자식 클래스의 생성자 호출 */
/* (4) 자식 클래스의 생성자를 마침 */
ColoredBox b = new ColoredBox(); //자식 클래스의 생성자 호출해서 객체 b 생성
}
}
- 부모 생성자와 자식 생성자의 시그니처가 같아야 한다.
class Parent { //부모 클래스
public Parent(String s) //생성자가 있으므로 기본 생성자 추가 X
}
class Child extends Parent { //자식 클래스
//생성자가 없으므로 기본 생성자 Child() 추가
//Child()는 제일 첫 행에서 부모 생성자 super() 호출
//부모 클래스에 Parent()가 없어서 오류 발생!
}
class Parent { //부모 클래스
//생성자가 없으므로 기본 생성자 Parent() 추가
}
class Child extends Parent { //자식 클래스
public Chile(String s) {
super(s); //부모 클래스에 Parent(String ...)이 없어서 오류 발생!
}
}
3차시 Triangle 클래스와 Member 클래스
class Triangle { //Triangle 클래스
double base; //필드: 삼각형의 속성 - 실수 값의 밑변
double height; //필드: 삼각형의 속성 - 실수 값의 높이
public Triangle() {} //기본 생성자
public Triangle(double base, double height) { //매개변수가 있는 생성자
this.base = base; //왼쪽이 필드 값, 오른 쪽이 매개변수
this.height = height;
}
public double getBase() { //밑변 접근자
return this.base; //밑변 필드 값 반환
}
public double getHeight() { //높이 접근자
return this.height; //높이 필드 값 반환
}
public double findArea() { //넓이 구하기 메서드
return (this.height * this.base / 2); //삼각형 넓이 반환
}
}
public class TriangleTest { //메인 메서드를 갖는 클래스
public static void main(String[] args) { //메인 메서드
Triangle t1 = new Triangle(10.0, 5.0); //Triangle 클래스의 생성자를 호출해서 t1 객체 생성
System.out.println(t1.findArea()); //객체 t1의 넓이 구하기
//클래스 외부에서 멤버 접근하는 것이므로 . 연산자를 이용해서 findArea()에 접근
}
}
다음 main() 메서드를 실행할 수 있도록 삼각형을 나타내는 Triangle 클래스에 생성자 2개를 추가하여 Triangle 클래스를 완성하시오. 조건 1: 밑변이 1.0이고 높이가 1.0인 객체 t2를 생성하는 생성자 구현하기 -> 기본생성자 이용하기 조건 2: 밑변과 높이가 모두 3.0인 객체 t3를 생성하는 생성자 구현하기 -> this() 이용하기 |
class Triangle {
private double base, height; //private으로 캡슐화
//private double height; //하나씩 선언 가능
/* 생성자 오버로딩 - 생성자 이름 같고 시그니처가 다름 */
public Triangle(double base, double height) { //(1) 매개변수가 있는 생성자
this.base = base;
this.height = height;
}
public Triangle() { //(2) 기본 생성자
this.base = 1.0;
this.height = 1.0;
}
public Triangle(double base) { //(3) 매개변수가 있는 생성자
this(base, 3.0); //this() 사용
//this()는 자기자신의 생성자에 접근하게 하므로 (1) 생성자에 접근
//this()는 생성자에서 다른 생성자를 호출
//this()는 가장 첫 번째 줄에 나와야 된다!
}
public double findArea() { //넓이 구하기 메서드
return (base*height)/2;
}
public double getBase() { //접근자
return this.base;
}
public double getHeight() { //접근자
return this.height;
}
}
public class TriangleTest {
public static void main(String[] args) {
Triangle t1 = new Triangle(10.0, 5.0);
Triangle t2 = new Triangle(); //밑변 1.0, 높이 1.0
Triangle t3 = new Triangle(3.0); //밑변=높이=3.0
System.out.println("t1=>" + t1.findArea()); //(1) 호출
System.out.println("t2=>" + t2.findArea()); //(2) 호출
System.out.println("t3=>" + t3.findArea()); //(3) 호출
}
}
class Member {
String name;
String id;
String pwd;
int age;
public Member(); //기본 생성자
public Member(String name, String id, String pwd, int age) { //매개변수 있는 생성자
this.name = name;
this.id = id;
this.pwd = pwd;
this.age = age;
}
/* 설정자 */
public void setName (String name) {
this.name = name; //이름 설정
}
public void setId (String id) {
this.id = id; //아이디 설정
}
public void setPwd (String pwd) {
this.pwd = pwd; //비밀번호 설정
}
public void setAge (String age) {
this.age = age; //나이 설정
}
/* 접근자 */
public String getName() {
return this.name; //이름 반환
}
public String getId() {
return this.id; //아이디 반환
}
public String getPwd() {
return this.pwd; //비밀번호 반환
}
public int getAge() {
return this.age; //나이 반환
}
}
public class MemberTest {
public static void main(String[] args) { //메인 메서드
Member mem1 = new Member("대한민국", "apple", "1234", 20); //mem1 객체 생성
/* 클래스 외부에서 접근자를 호출하는 것이므로 점 연산자 이용 */
System.out.println("이름 : " + mem1.getName()); //mem1 이름 출력
System.out.println("아아디 : " + mem1.getId()); //mem1 아이디 출력
System.out.println("나이 : " + mem1.getAge()); //mem1 나이 출력
}
}
'Study > JAVA' 카테고리의 다른 글
[JAVA] 9주차_추상 클래스와 인터페이스, 인터페이스의 상속, 인터페이스 구현과 타입 변환 (0) | 2022.05.01 |
---|---|
[JAVA] 7주차_추상 클래스와 인터페이스 (접근지정자, final과 객체의 타입 변환) (0) | 2022.04.14 |
[JAVA] 5주차_동적배열과 상속 (동적배열과 객체배열, 상속, Rectangle 클래스, OddEven 클래스) (0) | 2022.04.03 |
[JAVA] 4주차_정적멤버, 문자열, 배열 (this와 정적멤버, 문자열, 배열) (0) | 2022.03.25 |
[JAVA] 3주차_자바 문법과 객체 지향 (제어문과 메서드, 객체지향프로그래밍 개요, 접근자와 설정자) (0) | 2022.03.20 |