new 연산자와 같이 사용되어 클래스로부터 객체를 생성 할 때 호출되어 객체의 초기화를 담당한다.
class Constructor {
Constructor() { // ← 요함수가 생성자
code...;
}
}
사전적 용어로 '과적하다'라는 뜻의 오버로드는 C언어 등 절차지향 언어에서는 하나의 함수가 하나의 기능만을 구현해야 한다. 하지만, 자바에서는 하나의 메소드 이름으로 여러 기능을 구현 할 수 있다.
오버로딩의 조건
class Main(){
int i = 0;
String s = A;
Overload var = new Overload();
var.method();
var.method(s);
var.method(s, i);
// 각각 3개의 메소드는 이름은 같지만, 각각 다른기능을 한다.
}
class Overload() {
void method() {
code...;
}
int method(String s){
code...;
return s;
}
String method(String s, int i){
code...;
return i
}
}
부모 클래스로부터 상속받은 메소드를 자식 클래스에서 확장 및 재정의 하는 것
※ 상속(inheritance)
extends(상속)
예제
public class Main {
public static void main(String[] args) {
Mother mother = new Mother();
Son son = new Son();
son.printMotherAge();
}
}
class Mother {
int motherAge = 50;
Mother() {
System.out.println("welcome to Super class");
}
public void printMotherAge() {
System.out.println("Mother's Age : " + motherAge);
}
}
class Son extends Mother {
int sonAge = 23;
Son() {
System.out.println("welcome to sub class");
}
}
Mother mother = new Mother();
Main클래스에서 Mother클래스가 인스턴스화 되면서 생성자를 한 번 실행한다.
Son son = new Son();
class Son extends Mother { int sonAge = 23; Son() { System.out.println("welcome to sub class"); } }
Son클래스는 Mother클래스를 상속 받았다. Main클래스에서 Son클래스가 인스턴스화 될때 상속받은 Mother클래스의 생성자를 한번 실행한 후 자신의 생성자를 실행한다.
son.printMotherAge();
son객체의 메서드에는 printMotherAge()라는 함수는 없지만 Mother클레스를 상속 받았기 때문에 사용을 할 수 있다.
결과
implements(상속)
※ 반드시 재정의를 해줘야 하는 이유
1:1 상속이면 상관이 없지만 다중상속일 경우 '다이아몬드 문제'가 발생하기 때문이다.
※ 다이아몬드 문제
위의 예시처럼 GrandFather이라는 클래스가 myMethod()라는 이름의 메소드를 가지고 있다고 가정해 보자. 그리고 FatherA와 FatherB가 각각 오버라이딩하여 구현하였다면, FatherA와 FatherB를 모두 상속받는 Son클래스 입장에서는 어떤 부모의 myMethod()를 사용해야 할까? 이로인해 충돌이 발생한다.
참조 : https://siyoon210.tistory.com/125
예제
public class ImpleTest {
public static void main(String[] args) {
InterfaceExam test1 = new InterfaceExam();
test1.func1();
System.out.println();
InterfaceTest1 test2 = new InterfaceExam();
test2.func1();
}
}
interface InterfaceTest1 {
int num = 123;
void func1();
void func2();
}
interface InterfaceTest2 {
int num = 1234;
void func1();
void func2();
void func3();
}
class InterfaceExam implements InterfaceTest1, InterfaceTest2 {
InterfaceExam() {
System.out.println("hahaha");
}
@Override
public void func1() {
System.out.println("hello");
}
@Override
public void func2() {
System.out.println("world");
}
@Override
public void func3() {
// TODO Auto-generated method stub
}
}
interface InterfaceTest1 { int num = 123; void func1(); void func2(); } interface InterfaceTest2 { int num = 1234; void func1(); void func2(); void func3(); } class InterfaceExam implements InterfaceTest1, InterfaceTest2 { InterfaceExam() { System.out.println("hahaha"); } @Override public void func1() { System.out.println("hello"); } @Override public void func2() { System.out.println("world"); } @Override public void func3() { // TODO Auto-generated method stub } }
InterfaceTest1과 InterfaceTest2가 전부 InterfaceExam에게 상속 하였지만 메서드를 재정의 하였다.
재정의(오버라이드) 하지 않을 시 오류 출력.
InterfaceExam test1 = new InterfaceExam(); test1.func1(); System.out.println(); InterfaceTest1 test2 = new InterfaceExam(); test2.func1();
test1과 test2 각각의 참조형식이 다르지만 결과는 같은 것을 볼 수 있다.
결과
※ @Override의 용도
@는 어노테이션(Annotation)으로 직역하면 주석이라는 뜻이다. 이는 일반적인 주석과 다르게, 검증하는 기능을 한다.
코드상으로 검사했을 때 오버라이딩이 실제로 시행되지 않는다면 컴파일시 오류를 출력한다.
오버라이드(Override) 정리