toString을 재정의하기 (+ python)
개요
테스트코드에서 object의 필드값들이 다양한 type들로 이루어져 있었기 때문에 편한 게 String으로 변환하여 같은지를 테스트를 해보려고 했었다.
하지만 toString을 재정의해주지 않으면 최상위 클래스인 Object의 toString이 호출되어서 클래스풀네임@해시코드로 출력되기 때문에 원하는 행위를 하기 위해서는 반드시 재정의 해줘야한다.
toString 용도
주로 디버깅하거나 로깅을 할 때 사용된다. toString()을 사용하면 객체를 문자열로 랜더링을 하여 객체의 내부 상태를 문자열로 반환할 수 있다.
문제
코드
public class Person {
private final String name;
private final String age;
public Person(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
public class Main {
public static void main(String[] args) {
Person person1 = new Person("Jay", "40");
Person person2 = new Person("Jay", "40");
String person1ToString = person1.toString();
String person2ToString = person2.toString();
System.out.println(person1ToString);
System.out.println(person2ToString);
}
}
person object를 toString을 하게 되면 object의 toString이 호출되어 클래스풀네임@해시코드로 출력이 된다.
결과
org.example.Person@7ad041f3
org.example.Person@251a69d7
해결
1. toString() Override 하기
intellij에서 cmd+N 누르면 toString을 자동으로 override 해준다.
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
test 코드
class PersonTest {
@Test
public void 객체를_toString_했을_때_상태_확인하기() throws Exception {
// Given
Person person = new Person("Jay", "40");
// When
String result = person.toString();
// Then
String expected = "Person{name='Jay', age='40'}";
assertEquals(expected, result);
}
}
만약 클래스 타입을 포함한 Object인 경우에는 어떻게 toString을 해야 할까?
Person에 Address 타입을 가지고 있다고 해보자.
그러면 Address 클래스 안에서 toString을 재정의 해줘야 한다.
Address code
public class Address {
private final String city;
private final String state;
public Address( String city, String state) {
this.city = city;
this.state = state;
}
@Override
public String toString() {
return "Address{" +
"city='" + city + '\'' +
", state='" + state + '\'' +
'}';
}
}
}
test code
lombok 써서 빌더패턴을 사용하였다.
class PersonTest {
@Test
public void 객체를_포함한_객체를_toString_했을_때_상태_확인하기() throws Exception {
//Given
Person person = Person.builder()
.name("Jay")
.age("30")
.address(new Address("New York","New York"))
.build();
//When
String result = person.toString();
//Then
String expected = "Person{name='Jay', age='30', address=Address{city='New York', state='New York'}}";
assertEquals(expected, result);
}
}
2. Lombok @ToString
lombok toString을 쓰게 되면 모든 필드를 포함하여 toString이 재정의가 된다. 편하게 사용할 수 있지만 문제점이 있다.
만약 필드하나가 다른 클래스의 객체를 참조하고 있다면, 해당 참조된 객체의 toString() 메서드가 호출된다.
서로 참조가 된 경우에 두 클래스 간에 toString() 메서드가 서로를 호출하면서 무한 루프에 빠지게 된다.
그래서 직접 재정의해서 사용하는 것을 더 선호한다.
python에서는 toString을 어떻게 사용할까?
python에서는 java처럼 toString() 메서드는 없지만 같은 기능을 가진 여러 가지 메서드를 제공한다.그중에서 몇 가지만 이 포스팅에 넣고 더 알고 싶으면 참고한 문서링크를 넣었으니 확인해 보면 좋을 거 같다.
1. str()
객체를 문자열로 변환하는 내장함수이다. 다양한 타입의 인수를 받아 문자열로 변환한다.
# List
a = [1, 2, 3, 4]
b = str(a)
# integer
num = 1 + 5
numToString = str(num)
#String
num2 = "1+5"
num2ToString = str(num2)
print("List:", b)
print("Number:", numToString)
print("String:", num2ToString)
output
List: [1, 2, 3, 4]
Number: 6
String: 1+5
참고