JAVA(생성자, 오버로드, 오버라이드)

Hyeon_Su_Lee·2021년 12월 30일
0
post-custom-banner

요약

  • 생성자(Constructor)
  • 오버로드(Overload)
  • 오버라이드(Overriding)

생성자(Constructor)

new 연산자와 같이 사용되어 클래스로부터 객체를 생성 할 때 호출되어 객체의 초기화를 담당한다.

  • 클래스와 메서드명이 같다.
  • 리턴 값이 없다.
  • 클래스가 인스턴스화 될때 바로 실행되는 메서드 이다.
  • 리턴값이 없다는 의미의 void를 적어야 하지만, 모든 생성자가 리턴값이 없으므로 void를 생략한다.
class Constructor {
    Constructor() {  // ← 요함수가 생성자
    	code...;
    }
}

오버로드(Overload)

사전적 용어로 '과적하다'라는 뜻의 오버로드는 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
    }
}


오버라이드(Overriding)

부모 클래스로부터 상속받은 메소드를 자식 클래스에서 확장 및 재정의 하는 것

※ 상속(inheritance)

  • 기존에 정의되어 있는 클래스의 모든 필드와 메소드를 물려받는다.
  • 상속관계일때 참조형식을 부모클래스로 객체형식을 자식클래스로 인스턴스화가 가능하다.
  • 예외(Exception)는 부모 클래스의 메소드 보다 많이 선언할 수 없다.

extends(상속)

  • 대표적인 형태의 상속
  • 부모의 메소드를 그대로 사용할 수 있고, 오버라이딩 할 필요 없이 부모에 구현되어있는 것을 직접 사용
  • 자바는 다중상속이 지원되지 않는다(implements가 다중상속을 대신 해준다.)

예제

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(상속)

  • implements는 다중상속을 대신해준다.
  • class가 아닌 interface이다.
  • 상속을 받은 class는 부모의 method를 반드시 재정의(오버라이딩)해야한다.
  • 만약 다중상속을 받는 경우, 두개 이상의 부모 interface모두 같은 이름의 변수가 있고, 변수 사용시 해당 변수도 재 정의 해줘야 한다.
  • 그리고 두 interface모두 같은 이름의 함수가 존재하고 함수에 어떠한 기능이 있을 경우 자료형 앞에 어떤 함수가 default인지 적어줘야 한다.

※ 반드시 재정의를 해줘야 하는 이유
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) 정리

  1. extends는 일반 클래스 상속에 사용되고, implement는 interface 상속에 사용된다.
  2. class가 class를 상속받을 땐 extends를 사용하고, interface가 interface를 상속 받을 땐 extends를 사용한다.
  3. class가 interface를 사용할 땐 implements를 써야하고
  4. interface가 class를 사용할 땐 implements를 쓸수 없다.
  5. extends는 클래스 한 개만 상속 받을 수 있다.
  6. extends 자신 클래스는 부모 클래스의 기능을 사용한다.
  7. implements는 여러개 사용 가능하다.
  8. implements는 설계 목적으로 구현 가능하다.
  9. implements한 클래스는 implements의 내용을 다 사용해야 한다.
profile
어제 보다 오늘 더 발전하는 개발자
post-custom-banner

0개의 댓글