자바에서 모든 클래스의 최상위 부모는 항상 Object 클래스이다.
부모가 없는 클래스는 묵시적(Implicit)으로 Object 클래스를 상속한다.
이유
1. 공통기능 제공
- 공통된 메서드를 지원하기 때문에 일관성 있고 단순화된 프로그래밍 가능
2. 다형성의 기본 구현
- Object 클래스는 모든 객체를 참조할 수 있다. 다양한 타입의 객체를 통합적으로 처리 가능
Object의 다형성
Object 는 모든 객체 대상으로 다형적 참조를 할 수 있다. (모든 객체를 담을 수 있다)
그러나 모든 객체를 참조할 수 있다고 해도, 모든 메서드를 알고 있는 것은 아니다. 객체를 호출하려면 다운캐스팅이 필요하다.
당연히 Object 클래스의 메서드는 자식클래스에서 오버라이딩이 가능하다.
결과적으로 다형적 참조는 가능하지만 메서드 오버라이딩이 안되기 때문에 다형성을 활용하기에 한계가 있다.
Object 를 언제 활용하면 좋을까?
Object 배열
Object는 모든 타입의 객체를 담을 수 있다고 했다. 따라서 배열을 생성하면 모든 객체를 담을 수 있는 배열이 만들어진다.
package lang.object.poly;
public class ObjectPolyExample2 {
public static void main(String[] args) {
Dog dog = new Dog();
Car car = new Car();
Object object = new Object();
Object[] objects = {dog, car, object};
size(objects);
}
private static void size(Object[] objects) {
System.out.println("전달된 객체의 수는: " + objects.length);
}
}
size() 메서드
size 메서드는 배열에 담긴 객체의 수를 세는 역할을 담당한다. Object 타입 배열은 모든 객체를 담을 수 있기 때문에, 클래스가
추가되거나 변경되어도 이 메서드를 수정할 필요가 없다.
만약 Object가 없다면?
- 모든 객체를 담을 수 있는 배열을 만들 수 없다. 물론 커스텀해서 직접 customObject를 만들어 상속받으면 되겠지만, 번거로움과
개발자들끼리 각각 다른 Object 클래스를 만들기에 호환되지 않는 일이 발생할 것이다.
toString()
toString()은 객체의 정보를 문자열 형태로 제공한다. 디버깅과 로깅에 유용하게 사용된다.
Object 클래스에 있는 기능이므로 모든 클래스에서 오버라이딩 할 수 있다.
toString()은 기본적으로 오버라이딩 하지않으면 객체의 해시코드를 16진수로 제공한다.
println()과 toString()
두가지 모두 객체 정보를 출력하게 되면 해시코드를 출력한다. 그 이유는 println 메서드 내부에서 toString을 호출하기 때문.
따라서 println()을 사용할 때 toString()을 직접 호출할 필요 없이 바로 객체를 전달하면 된다.
toString() 오버라이딩
위에서 언급했듯 오버라이딩 하지않으면 객체의 참조값만 제공한다고 했다. 객체의 자세한 정보를 얻고싶을 땐 오버라이딩 하자
(커맨드 + n으로 generate에서 toString을 생성할 수 있음)
@Override
public String toString() {
return "Dog{" +
"dogName='" + dogName + '\'' +
", age=" + age +
'}';
}
그럼 힘들이지 않고 쉽게 객체의 정보를 자세하게 출력할 수 있다.
Object와 OCP
Object가 없다면 OCP관점에서 어떤일이 생길지 생각해보면, Object가 제공하는 toString()메서드가 없으니 서로 관계없는
객체끼리의 정보는 출력하기 어려울 것이다. 출력하려면 일일이 클래스마다 별도의 메서드를 작성해야 할 것이다.
그리고 그 클래스는 출력하기 위해 구체적인 타입에 의존하게 된다. 이는 OCP 원칙에 벗어난다.
추상적인 것에 의존
public class ObjectPrinter {
public static void print(Object object) {
String string = "객체 정보 출력:" + object.toString();
System.out.println(string);
}
Object 클래스를 의존하는 메서드이다. 이 메서드는 Car, Dog를 의존하는것이 아닌 추상적인 클래스 Object를 의존한다.
다형적 참조 문제를 해결할 수 있게 된 것이다.
ObjectPrinter와 Object를 사용하는 구조는 다형성을 매우 잘 활용하고 있다. (다형적 참조와 메서드 오버라이딩이 적절하다)
System.out.println()
ObjectPrinter() 메서드는 println()의 작동방식을 설명하기 위해 만든 메서드이다. println 메서드도 Object 타입의 매개변수를
사용하고 내부에서 toString()을 호출하기 때문에 우리가 공부하면서 어느 클래스에서든 sout을 찍어도 출력이 된 것이다.
정적 관계 / 동적 관계
정적관계: 컴파일 시간에 결정된다. 주로 클래스 간의 관계를 의미함. 클래스 내에서 사용하는 타입들만 보면 쉽게 파악 가능한 관계
동적관계: 런타임 시간에 결정된다. Object obj에 인자로 어떤 객체가 전달될 지 실행해봐야 알 수 있는 관계
'Java' 카테고리의 다른 글
String 클래스 (1) | 2024.10.15 |
---|---|
불변 객체 (0) | 2024.10.10 |
제네릭 - 제한된 타입 파라미터/ 와일드카드 (0) | 2024.07.11 |
제네릭(Generic) 메소드 (0) | 2024.07.11 |
제네릭 (Generic) (0) | 2024.07.10 |