Overloading = "과적하다"
자바의 한 클래스 내에
이미 사용하려는 이름과 같은 이름을 가진 메소드
가 있더라도,
매개변수의 개수 or 타입
이 다르면
같은 이름을 사용해서 메소드를 정의 O
메서드의 이름이 같고,
매개변수의 개수 or 타입 or 순서가 달라야 한다.
주의
결론
public int overloadTest() {
return 0; // 매개변수의 개수: 0개
}
public int overloadTest(String test) {
return 1; // 매개변수의 개수: 1개
}
public int overloadTest(String test) { // 매개변수의 타입: String
return 1;
}
public int overloadTest(int test) { // 매개변수의 타입: int
return 1;
}
// Q. 다음의 add메서드를 바르게 오버로딩한 것은?
long add (int a, int b) {
return a+b;
}
// A1.
long add (int a, long b) { // 반환타입 long은 고려 대상 X
return a+b;
}
// A2.
int add (int a, long b) { // 반환타입 int는 고려 대상 X
return a+b;
}
public class MyClass {
// 오버로딩 될 plus메서드
public int plus (int x, int y) {
return x + y;
}
// 오버로딩 1 : 매개변수의 타입은 동일, 개수 다름
public int plus (int x, int y, int z) {
return x + y + z;
}
// 오버로딩 2 : 매개변수의 타입은 다름, 개수는 동일
public string plus (string x, string y) {
return x + y;
}
}
public class Car {
String name;
int number;
public Car (String name) {
this.name = name;
}
public Car() {
}
public Car (String name, int number) {
this.name = name;
this.number = number;
}
}
public static void main(String[] args) {
Car c1 = new Car("소방차");
Car c2 = new Car();
Car c3 = new Car("구급차", 111);
}
public class PrintStream extends FilterOutputStream
implements Appendable, Closeable
{
...
public void println() {
newLine();
}
public void println(boolean x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(char x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(int x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(float x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(char[] x) {
if (getClass() == PrintStream.class) {
writeln(x);
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(String x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
newLine();
}
}
}
public void println(Object x) {
String s = String.valueOf(x);
if (getClass() == PrintStream.class) {
// need to apply String.valueOf again since first invocation
// might return null
writeln(String.valueOf(s));
} else {
synchronized (this) {
print(s);
newLine();
}
}
}
...
}
메서드의 이름을 절약
println()
는 printlnInt()
, printlnDouble()
처럼 메서드명이 길어지고 낭비 되었을 것이다메서드 이름 하나로, 상황에 따른 동작을 개별로 정의 할 수 있다
입력하는 값(매개변수)이 다르지만 같은 기능을 수행하는 경우가 많을 때, 사용성 및 효율을 높일 수 있다
Point 클래스
clasa point {
int x;
int y;
String getLocation() {
return x + y;
}
}
Point3D 클래스
clasa Point3D {
int z;
String getLocation() { // 오버라이딩 -> 상속받은 메서드를 자신에게 맞게 재정의했다(+ z 추가)
return x + y + z;
}
}
overriding = "... 의 위를 덮다."
부모 클래스로부터 상속받은 메서드의 내용을 변경(재정의)
하여 사용하는 것
→ 부모로부터 받은 메소드의 로직을 원하는대로 변경
→ 다형성(객체지향 언어의 특징)
주의!
부모 메소드와 동일하거나 추가되어야 함.
감소되면 X
@override 는 필수인가?
이 어노테잉션은 일종의 안전장치다.
어떤 라이브러리에 속한 클래스를 상속받아, 특정 메서드를 override 했다.해당 라이브러리가 업데이트되면서 메서드의 시그네쳐가 바뀌는 경우,
이전엔 override 한 메서드가 새 버전에서는 그냥 새로 추가된 메서드로 인식될 뿐,컴파일 오류가 발생하지 않기 때문에
개발자는 동작이 달라진 걸 알아채기 어렵다.
→ @override 이 없는 경우, 해당 메서드를 overriding 한 것인지 여부를 직접 상위 클래에 가서 찾아야 하는데
단순 추상 클래스(or 인터페이스) 하나만 있다면 상관없지만, 여러가지 상속 깊이가 있는 경우에는 바로 찾아서 확인하기도 힘들다.이런 부류의 문제를 방지하기 위해
@Override
를 사용하는 것 (= 클래스 구조를 더 쉽게 인식 가능하다.)
→ 만약, @Override 이 붙은 메서드가 부모 메서드를 override 하지 않는다면, 컴파일 시 오류가 발생!
접근 제한 정도 : = 또는 ↓ (같거나 더 약하게)
예시 1 : 부모 메소드: public --> 자식 메소드: public 가능
예시 2 : 부모 메소드: default --> 자식 메소드: default, public, protected 가능
예외의 개수 : 조상 클래스 > 자식 클래스
부모 클래스
class Parent {
void parentMethod() throws IOException, SQLException { // 2개
...
}
}
자식 클래스
class Child extencs Parent {
void parentMethod() throws IOException { // 1개
...
}
}
public class Parent {
public void overridingTest() {
System.out.println("부모 메서드의 내용");
}
}
// Child 클래스(자식)가 Parent 클래스(부모)의 overridingTest()메서드를 상속받아 재사용
class Child extends Parent{
// 메서드의 선언부는 조상의 메서드와 일치
// 메서드의 내용만 재정의하여 사용
@Override
public void overridingTest() {
System.out.println("상속받은 부모메서드의 내용을 수정하여 자식메서드의 내용으로 재사용");
}
}
부모 클래스
public class Parent {
public void method1() {
System.out.println("Parent-method1()");
}
public void method2() {
System.out.println("Parent-method2()");
}
}
자식 클래스
public class Child extends Parent {
// 부모 클래스의 메소드 재정의
@Override
public void method2() {
System.out.println("Child-method2()");
}
public void method3() {
System.out.println("Child-method3()");
}
}
ChildExample
public class ChildExample {
public static void main(String[] args) {
Child child = new Child();
Parent parent = child; // 자동 타입 반환
parent.method1();
parent.method2(); // 부모 클래스가 아닌, 자식 클래스에서 재정의된 메소드가 호출됨
parent.method3(); // 호출 불가능
}
}
원칙 : 부모 타입으로 자동 타입 변환 된 이후 --> 부모 클래스의 필드, 메소드만 접근 가능
예외 : 자식 클래스에 메소드 재정의를 한다면, 자식 클래스의 메소드가 대신 호출됨 ('다형성'과 관련)
public class Car {
public void run() {
System.out.println("Car의 run메서드")
}
}
public class Bus extends Car { // 자식 클래스 Bus
public void run() {
super.run(); // 부모 클래스 Car의 메서드run 호출
System.out.println("Bus의 run메서드")
}
}
/* 실행 결과
Car의 run메서드
Bus의 run메서드
*/
super
키워드를 사용하면, 자식클래스에서 부모클래스의 메서드를 호출 가능오버로딩 : 기존에 없는 새로운 메서드를 추가 new
오버라이딩 : 상속받은 메서드 내용을 변경 modify
change
참고: 오버로딩(Overloading)과 오버라이딩(overriding) 차이
참고: [Java] 오버로딩 & 오버라이딩 차이 비교 정리(오버로딩, 오버라이딩 차이점)
참고: 오버로딩과 오버라이딩 차이와 예제