오버라이딩
- 부모클래스에서 상속받은 메소드를 재정의 하는 것
- 상속관계에 있는 부모클래스로부터 상속받은 메소드를 하위클래스에서 그대로 사용하지 않고 하위클래스에 맞게 내용을 변경하는 것 ( 무조건 상속관계에서만 발생한다 )
오버라이딩 조건 : 반환타입 + 메소드이름 + 매개변수이 다 부모클래스와 동일해야 한다. 그러나 구현내용만 다르게 정의해야 한다 ( 접근제한자는 달라도 상관없지만, 부모의 접근제한과 동일하거나 더 느슨한 접근제한만 가능하다)
오버라이딩의 목적 : 오버라이딩한 ( 메소드를 재정의한 ) 메소드를 부모타입의 참조변수로 실행하기 위해서
오버라이딩의 예
public class Printer {
String black;
public void print() {
System.out.println("흑백으로 인쇄");
}
}
public class ColorPrinter extends Printer {
// Printer 객체의 print() 메소드를 재정의 하였다
public void print() {
System.out.println("컬러로 인쇄합니다");
}
}
public class PhotoPrinter extends ColorPrinter {
public void print() {
System.out.println("사진품질로 인쇄합니다");
}
}
public class PrinterApp1 {
public static void main(String[] args) {
Printer p1 = new Printer();
p1.print(); // Printer 객체의 print()가 실행됨
ColorPrinter p2 = new ColorPrinter();
p2.print(); // ColorPrinter 객체의 재정의된 print()가 실행됨
Printer p3 = new ColorPrinter();
p3.print();
}
}
p3.print(); 코드의 결과는 ColorPrinter 객체의 재정의된 print() 메소드가 실행된다
Printer 객체를 참조하고 있어도 실제 생성한 ColorPrinter 객체의 재정의된 print()가 실행된다
즉, Printer 객체 타입의 참조변수로 자식 Printer 객체를 참조하고 있을 때 print()를 실행하면 실제 생성된 객체에 오버라이딩된 print()가 실행된다
참조변수 타입과 다르더라 내가 실제로 생성한 객체의 메소드가 실행된다
오버라이딩을 사용한 다른 예제
public class PC {
Printer p;
public void printDocument() {
p.print();
}
}
public class PCApp {
public static void main(String[] args) {
// 다양한 프린터객체를 준비한다.
Printer p1 = new Printer();
ColorPrinter p2 = new ColorPrinter();
PhotoPrinter p3 = new PhotoPrinter();
// 컴퓨터 객체를 준비한다
PC pc = new PC();
// 컴퓨터 객체와 프린터 객체를 조립한다
pc.p = p1;
// 문서를 인쇄한다
pc.printDocument();
}
}
pc.p = p1;
참조변수 p에 무엇을 대입하냐에 따라 출력값이 달라진다
오버로딩과의 차이
오버로딩의 정의 : 하나의 클래스 안에 매개변수가 서로 다른 같은 이름의 메소드를 여러개 정의하는 것
오버로딩의 목적 : 유사한 작업은 일관된 이름으로 구현하자
오버로딩의 예
public class Calculator{
public int plus(int a, int b) {
return a + b;
}
public int plus(int a, int b, int c) {
return a + b + c;
}
public double plus(double a, double b) {
return a + b;
}
public double plus(double a, double b, double c) {
return a + b + c;
}
- 매개변수의 구성( 매개변수의 수, 또는 데이터 타입 ) 이 다르면 같은 이름의 메소드를 여러 개 정의할 수 있다
추상화
- 추상화는 객체에서 공통된 속성과 기능을 추출하는 것
- 자바에서 추상화는 공통된 속성과 기능을 모아서 추상클래스(Abstract Class)나 인터페이스(Interface)를 정의하는 것
- 공통 속성은 변수나 상수로 표현하고, 기능은 추상메소드로 표현
- 추상화를 통해서 하위 클래스들이 구현해야할 공통 기능을 정의할 수 있다
추상메소드
- 추상메소드는 구현부가 없는 메소드
- 추상메소드는 추상클래스와 인터페이스에만 정의할 수 있다 ( 일반적인 클래스. 즉, 구현 클래스는 추상 메소드를 보유할 수 없다)
- 추상메소드를 상속받았다면 반드시 오버라이딩을 통해 구현부가 있는 메소드로 만들어야 한다
// abstract를 붙여야 추상 메소드로 선언할 수 있다
abstract void sample();
추상클래스
- 추상클래스는 추상메소드를 보유하는 클래스
- 추상클래스의 목적은 추상클래스를 상속받은 하위클래스가 추상메소드를 재정의(오버라이딩)하도록 한다
- 인스턴스 변수, 인스턴스 메소드, 클래스 변수, 클래스 메소드, 생성자, 추상메소드 모두를 보유할 수 있다. ( new 연산자를 이용해서 객체 생성할 수 없다 )
추상 클래스의 목적 : 하위 클래스들이 반드시 구현할 기능을 추상메소드를 사용해서 추상화한다
모든 하위 클래스가 동일한 동작하는 기능을 추상 클래스에서 구현해서 상속시킴으로서 하위 클래스의 구현부담을 감소시켜준다 ( 인터페이스의 중간단계 역할을 할 수 있다)
// 추상클래스는 abstract가 붙는다
public abstract class Sample {
// 추상 메소드
abstract void test1();
}
추상메소드와 추상클래스 예시
// 추상메소드를 갖고 있기 때문에
// 추상클래스
public abstract class Chart {
// 추상메소드 정의하기
// 구현부가 없는 메소드
public abstract void draw();
}
// 구현클래스 정의하기
// 추상 메소드를 보유할 수 없다
// 만약 부모로부터 추상 메소드를 상속받았으면, 반드시 메소드 재정의해야 한다
public class LineChart extends Chart{
// 오버라이드 어노테이션
// 부모의 메소드를 재정의 하는 것을 나타낸다
@Override
public void draw() {
System.out.println("꺾은선 그래프를 그립니다");
}
}
다형성
오버로딩(메소드 중복정의), 오버라이딩(메소드 재정의), 추상화, 인터페이스 등을 활용해서 다형성을 구현할 수 있다
오버로딩(메소드 중복정의)와 다형성
- 동일한 이름의 메소드를 호출하지만, 매개변수에 따라서 실행결과가 다르게 나타난다
public class DataParser {
Data[] parseData(String csv) {
// csv파일을 해석해서 Data배열을 반환한다.
}
Data[] parseData(URL url) {
// 지정된 url에서 데이터을 읽어서 Data배열을 반환한다.
}
Data[] parseData(ExcelDocument xls) {
// 엑셀파일을 해석해서 Data배열을 반환한다.
}
}
DataParser 클래스의 parseData() 메소드는 매개변수로 전달받는 값의 종류가 달라지면 실행내용이 달라진다
오버라이딩(메소드 재정의)와 다형성
- 재정의된 메소드는 상위 클래스타입으로 형변환되어 있더라도 실제 생성된 객체의 재정의된 메소드가 실행된다
오버라이딩을 이용한 다형성 예제
public class Phone {
String tel;
void call() {
전화통화 제공
}
void sms() {
문자 송수신 지원
}
}
public class SmartPhone extends Phone {
String ip;
@Override
void call() {
스마트폰 영상통화 지원
}
void web() {
인터넷 지원
}
void pay() {
앱 결재 지원
}
}
public class Iphone extends SmartPhone {
@Override
void call() {
페이스타임 통화 지원
}
@Override
void web() {
사파리 웹 브라우저로 인터넷 지원
}
@Override
void pay() {
애플페이 결재 지원
}
void faceId() {
얼굴인식 인증 지원
}
}
public class Galaxy extends SmartPhone {
@Overide
void web() {
삼성 웹 브라우저로 인터넷 지원
}
@Override
void pay() {
삼성페이 결재 지원
}
void dex() {
삼성 Dex모드 지원
}
}
재정의된 메소드 실행하기
public static void main(String[] args) {
Phone p1 = new Iphone();
SmartPhone p2 = new Iphone();
SmartPhone p3 = new Galaxy();
p1.call(); // 페이스타임 통화 실행됨
p1.sms(); // 문자송수신 지원이 실행됨
p1.web(); // 컴파일 오류
p1.pay(); // 컴파일 오류
p2.call(); // 페이스타임 통화 실행됨
p2.sms(); // 문자송수신 지원이 실행됨
p2.web(); // 사파리 웹브라우저 지원이 실행됨
p2.pay(); // 애플페이 결재 지원이 실행됨
p3.call(); // 영상통화 지원이 실행됨
p3.sms(); // 문자송수신 지원이 실행됨
p3.web(); // 삼성 웹브라우저 지원이 실행됨
p3.pay(); // 삼성페이 결재 지원이 실행됨
}
다형성 요약
- 오버로딩(메소드 중복정의)
- 하나의 클래스 안에 동일한 이름의 메소드를 여러 개 정의하는 것
- 접근제한자, 반환타입은 상관없음
- 메소드이름이 동일하고, 매개변수의 타입, 갯수가 다르기만 하면 된다
- 목적
- 하나의 클래스안에 매개변수만 다르고 수행하는 작업은 비슷한 경우 일관성있고 동일한 메소드 이름으로 실행하게 한다
- 오버라이딩(메소드 재정의)
- 상속/구현관계에 있는 클래스의 자식 클래스에서 부모로부터 물려받은 메소드를 재정의 하는 것
- 방법
- 반환타입, 메소드이름, 매개변수의 갯수와 타입이 모두 일치하고, 구현내용(수행문의 내용)만 재정의 하는 것
- 접근제한자는 부모측의 접근제한자와 동일하거나 더 느슨하게 정의해야 한다
- 내용
- 동일한 업무지만 자식클래스들 마다 세부 업무내용이 다른 경우 구체적인 구현을 자식클래스들이 부모의 메소드를 재정의해서 구현하도록 하는 것
- 목적
- 부모의 메소드와 자식의 메소드가 메소드 재정의 관계를 형성하게 되면 부모객체를 참조하고 있어도 자식에 재정의된 메소드를 실행할 수 있게 한다
- 필드의 다형성, 매개변수의 다형성을 획득할 수 있다.
- 다형성
- 실행방법은 동일하지만 사용하는 객체가 달라지면 다른 결과가 발현되는 것
- 객체지향 프로그래밍의 주요한 특징
- 메소드 재정의, 추상화, 인터페이스 등의 기술을 활용해서 다양하게 활용할 수 있음
'Java' 카테고리의 다른 글
Java_접근제어자, 내부클래스(oop) (0) | 2023.11.13 |
---|---|
Java_인터페이스(oop) (1) | 2023.11.10 |
Java_상속, Object, 클래스 형변환(oop) (0) | 2023.11.08 |
Java_static변수와 static메소드 (oop) (0) | 2023.11.08 |
Java_생성자, 메소드 예시(oop) (0) | 2023.11.02 |