[Java] 자바의 정석 7장 (2) - Object 클래스, 오버라이딩

토닉·2021년 9월 17일
0

Java

목록 보기
11/13
post-thumbnail

Object

  • 모든 클래스(객체)의 부모(조상)
  • 부모가 없는 클래스는 자동으로 Object 클래스를 상속받는다.
  • 결국 모든 클래스는 Object를 상속받기 때문에 Object클래스에 정의된 11개의 메서드를 상속받는다.(toString(), equals(Object obj), hashCode() ...)
class Tv {} // 이 클래스는 자동적으로 Object 클래스를 상속받는다.
class Tv extends Object {} // 같은 코드

class SmartTv extends Tv {}

메서드

toString()

  • 클래스의 이름과 주소를 String으로 반환"클래스이름@객체의 주소"
  • 모든 클래스가 사용 가능
  • println()안에 인스턴스 참조변수의 값을 넣은 것과 같은 결과를 반환한다.
public class Ex7_1 {
	public static void main(String args[]) {
		Point2D p2 = new Point2D();
		Point3D p3 = new Point3D();
		p2.x = 1;
		p2.y = 2;
		p3.x = 3;
		p3.y = 4;
		p3.z = 5;
		System.out.println(p2.toString()); // Point2D@28d93b30
    System.out.println(p2); // Point2D@28d93b30
		System.out.println(p3.toString()); // Point3D@1b6d3586
    System.out.println(p3); // Point2D@28d93b30
	}
}

class Point2D { // extends Object
	int x;
	int y;
}

class Point3D extends Point2D {
	int z;
}

오버라이딩(overriding)

상속받은 조상의 메서드를 자신에 맞게 변경하는 것

규칙

  • 선언부가 조상 클래스의 메서드와 일치해야 한다.(반환값, 이름, 인자)
  • 접근 제어자(public, protected, private, default)를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
  • 예외(throws)는 조상 클래스의 메서드보다 많이 선언할 수 없다.
public class Ex7_1 {
	public static void main(String args[]) {
		Point2D p2 = new Point2D();
		Point3D p3 = new Point3D();
		p2.x = 1;
		p2.y = 2;
		p3.x = 3;
		p3.y = 4;
		p3.z = 5;
		System.out.println(p2.getLocation());
		System.out.println(p3.getLocation());
	}
}

class Point2D {
	int x;
	int y;

	String getLocation(){
		return "(x,y) : " + "(" + x + "," + y + ")";
	}

}

class Point3D extends Point2D {
	int z;

	String getLocation(){ // 오버라이딩
		return "(x,y,z) : " + "(" + x + "," + y + ","+ z + ")";
	}
}

Point2D의 메서드를 Point3D가 사용하면 z가 빠지게 됩니다.

따라서 오버라이딩을 통해 Point3D일 때는 z를 포함한 getLocation()메서드를 작성해 주어야 합니다.

오버라이딩을 Object의 메서드에 활용할 수 있습니다.

public class Ex7_1 {
	public static void main(String args[]) {
		Point2D p2 = new Point2D();
		Point3D p3 = new Point3D();
		p2.x = 1;
		p2.y = 2;
		p3.x = 3;
		p3.y = 4;
		p3.z = 5;
    System.out.println(p2);
		System.out.println(p3);
	}
}

class Point2D {
	int x;
	int y;

	// Object의 toString() 메서드 오버라이딩
	public String toString(){
		return "(x,y) : " + "(" + x + "," + y + ")";
	}

}

class Point3D extends Point2D {
	int z;
	
	// Object의 toString() 메서드 오버라이딩
	public String toString(){
		return "(x,y,z) : " + "(" + x + "," + y + ","+ z + ")";
	}
}

public을 붙인 이유: 오버라이딩을 할 때 선언부는 똑같이 작성해야 합니다.

오버로딩 vs 오버라이딩

  • 오버로딩: 기존에 없는 새로운 메서드를 정의하는 것(단 같은 클래스 내에 이름이 같은 메서드)
  • 오버라이딩: 상속받은 메서드의 내용을 변경하는 것
class Parent {
    void parentMethod() {}
}

class Child extends Parent {
    void parentMethod() {} // 오버라이딩
    void parentMethod(int i) {} // 오버로딩

    void childMethod() {} // 메서드 정의
    void childMethod(int i) {} // 오버로딩
    void childMethod() {} // 에러(중복 정의)

}

참조변수 super

  • 객체 자신을 가리키는 참조변수, 인스턴스 메서드 내에만 존재
  • 조상의 멤버와 자신의 멤버를 구별할 때 사용

super, this의 차이점
super : 조상멤버와 자손멤버를 구별할 때 사용
this : 지역변수와 인스턴스 변수를 구별할 때 사용

public class Test {
	public static void main(String args[]) {
		MyChild mc = new MyChild();
		mc.method();
	}
}

class MyParent {
	int x = 20;
}

class MyChild extends MyParent {
	int x = 10;
	void method() {
		System.out.println(super.x); // super.x = 20
		System.out.println(this.x); // this.x = 10
	}
}

만약 MyChild 클래스에 x 변수가 없다면..
자손멤버와 조상멤버를 따로 구별할 이유가 없기 때문에 자손멤버의 x도 조상의 변수를 상속받습니다.
super.x = 20, this.x = 20으로 같습니다.

조상의 생성자 super()

  • 조상의 생성자를 호출할 때 사용(조상의 멤버를 초기화하기 위해)
  • 조상의 멤버는 조상의 생성자를 호출해서 초기화

조건

  • 생성자의 첫 줄에 반드시 생성자를 호출해야 한다!!(중요)
  • 그렇지 않으면 컴파일러가 생성자의 첫 줄에 super();를 삽입
class MyPoint2D{
    int x,y;
    
    MyPoint2D(int x, int y){
        this.x = x;
        this.y = y;
    }
}

// super() 사용
class MyPoint3D extends MyPoint2D{
    int z;
    
    MyPoint3D(int x, int y, int z){
        super(x,y); // 조상 클래스의 생성자를 호출 - MyPoint2D(int x, int y)
        this.z = z;
    }
}

// 직접 초기화
class MyPoint3D extends MyPoint2D{
    int z;
    
    MyPoint3D(int x, int y, int z){
        // super(); 컴파일러가 이 코드를 자동으로 생성한다.
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

조상의 멤버는 조상의 생성자(super())로 초기화하는 것이 좋은 방법입니다.

profile
우아한테크코스 4기 교육생

0개의 댓글