안녕하세요! 쏘코입니다.
이번 포스팅에서는 자바 문서 보는 법 영상에서 설명하고 있는 클래스와 인스턴스, 그리고 상속에 대해서 알아보도록 하겠습니다.
목차
0. 클래스
클래스에 대해서 좀 더 알아봅시다!
ClassApp이라는 클래스를 만들겠습니다.
Math이라는 기본 클래스 내에 있는 PI라는 변수를 출력하면 3.1415925...가 출력됩니다.
Math 클래스 내부에 정의되어 있는 floor, ceil 메소드에 1.6이라는 매개변수를 넣으면 각각 1.0과 2.0이 반환됩니다.
그리고 그 값을 출력한 결과가 1.0과 2.0이 되는 것이죠!
이전에 한 내용의 복습이지만, 클래스의 기본에 대해서 좀 더 명확히 한 후에 다시 사용하니 깔끔하게 정리가 되네요 :)
public class ClassApp {
public static void main(String[] args) {
System.out.println(Math.PI); // Math 안의 PI를 출력
System.out.println(Math.floor(1.6)); // 1.0
System.out.println(Math.ceil(1.6)); // 2.0
// 클래스는 서로 연관된 변수와 메소드들을 모아서 이름을 붙인것!!
}
}
1. 인스턴스
클래스는 서로 연관된 변수와 메소드들을 모아서 이름을 붙인 것이었습니다.
그렇다면 인스턴스는 무엇일까요?
이번에는 InstanceApp이라는 클래스를 만들겠습니다.
new PrintWriter("result1.txt");
라는 명령을 통해 PrintWriter 형태의 객체 하나를 만듭니다.
PrintWriter p1 = new PrintWriter("result1.txt");
라는 명령을 통해 그 객체를 PrintWriter형태의 변수인 p1에 할당(=)합니다.
그리고 PrintWriter 형태의 변수에서 사용할 수 있는 write라는 변수와 close라는 변수를 사용했습니다.
p1.write("Hello 1");
p1.close();
저는 p1과 p2로 총 2개를 만들었어요!
이렇게만 하면 분명 빨간 밑줄이 그어지면서 에러가 났다고 할 것입니다.
PrintWriter는 Math처럼 기본적으로 불러오는 클래스가 아니기 때문입니다.
이 문제는 java.io.PrintWriter를 import 하면 해결됩니다.
여기까지 했는데도 빨간 밑줄이 뜨죠?
예외 처리가 되지 않았기 때문에 발생하는 경고입니다.
지금 예외 처리를 이해하기에는 조금 어려울 수 있으니, 우선 Add throws declaration을 눌러서 고쳐봅시다!
java.io.FilenotFoundException이 import되었고,
추가적으로 IOException - java.io를 더블클릭해서 예외 처리를 마무리해줍니다.
이 상태로 프로그램을 실행하면 result1.txt, result2.txt가 생성됩니다!!
지금까지의 과정에서 우리는 PrintWriter를 바로 쓰는게 아니라 new PrintWriter로 생성해서 PrintWriter 변수인 p1에 넣어서 사용했습니다.
왜 이렇게 했을까요?
아래 예시를 살펴봅시다.
write("result1.txt", "Hello 1");
과 같은 방식으로 위에서 했던 작업을 똑같이 할 수 있다고 가정합시다.
첫 번째 케이스는 매번 어떤 텍스트의 어떤 내용을 설정해야 할지 설정해야 합니다.
하지만 두 번째 케이스는 new를 통해 인스턴스를 만들었고, 그 인스턴스는 내부적으로 각자의 상태를 가지고 있습니다.
p1은 result1.txt, p2는 result2.txt라는 상태를 이미 가지고 있죠.
이 상태에서는 보다 깔끔하게 어떤 요소를 어떻게 수정할 것인지를 파악할 수 있고 실제로 사용하기에도 편합니다.
write가 아니라 다른 작업이 병행되는 경우 이 차이는 더 커지겠죠?
클래스를 만드는 사람들은 인스턴스가 필요 없이 일회용으로 쓸 수 있는 경우
Math.PI
형태로 사용할 수 있게 하고,
만약 그 클래스가 하는 작업이 꼬리에 꼬리를 물면서 해야되는 작업이라면
PrintWriter p1 = new PrintWriter("result1.txt");
형태로 클래스를 복제한 인스턴스를 만들어서 사용할 수 있도록 하는 것입니다.
실제로 Math는 Constructor(생성자)가 없고, PrintWriter는 Constructor(생성자)가 있습니다.
Math같이 생성자가 없는 경우는 대부분 인스턴스가 아닌 일회용으로 쓰인다고 생각하시면 됩니다.
생성자가 있다면 이 생성자를 이용해서 인스턴스를 만들어낼 수 있다는 이야기가 되겠죠!
정리하면 new 뒤에 붙은 친구가 생성자가 되고, 앞에 new가 붙는 순간 그 클래스가 복제되어 인스턴스가 만들어집니다.
이렇게 만들어진 인스턴스는 PrintWriter형태의 데이터이기 때문에 PrintWriter 변수에만 할당될 수 있는 것이죠.
더욱 쉽게 이해하기 위해 예시를 들자면
PrintWriter이라는 클래스가 붕어빵 틀이 되고, 이 붕어빵 틀로 p1이라는 붕어빵을 찍어 낸겁니다!!
이걸 컴퓨터적인 용어로 말하면 PrintWriter는 클래스이고, new PrintWriter("result1.txt")는 인스턴스이고, p1은 객체가 되는 것이죠.
2. 상속
PrintWriter의 API 설명을 보면 위쪽에 패키지가 3개나 적혀있는게 보입니다.
왜 이렇게 적혀있을까요?
PrintWriter 클래스를 만든 사람은, 처음부터 끝까지 만들기 귀찮았던 것입니다.
그래서 Object클래스의 자료를 상속받아서 쓸 수 있는 부분을 쓰고, 그 중에서 Writer 클래스의 자료를 상속받아서 쓸 수 있는 부분을 사용하고, 남은 부분을 정의한 것이죠.
이 말은 PrintWriter로 만든 객체는 Object, Writer, PrintWriter의 성질을 모두 가지고 있다는 말과 같습니다.
이클립스로 돌아와서, 우리가 사용한 PrintWriter에서 오른쪽 마우스키를 누르고, Open Type Hierarchy를 누릅니다.
그러면 오른쪽 창에 Object, Writer, PrintWriter가 순서대로 나타납니다.
이 순서의 의미는 PrintWriter는 Writer를 상속했고, Writer는 Object를 상속했다는 것입니다.
또 각각의 클래스를 클릭해보면, 클래스에 속해있는 메소드들도 볼 수 있습니다.
PrintWriter에는 toString 메소드가 없습니다. 하지만 Object를 상속받았죠? 그렇기 때문에 toString을 사용할 수 있습니다.
사용하려는 메소드가 원래 클래스에 정의되어있지 않으면 부모 클래스 가서 찾고, 거기에도 없으면 그 부모 클래스에 가서 찾고, 끝까지 갔는데도 없으면 그때서야 에러를 출력하게 됩니다.
만약 상속을 해주는 부모 클래스와, 상속을 받는 자식 클래스에 같은 이름의 메소드가 있다면 어떻게 될까요?
자식 클래스에서 그 메소드를 사용하는 경우 자식 클래스에서 정의한 메소드가 작동하게 됩니다.
예를 들자면 write라는 메소드가 Writer, PrintWriter 클래스에 둘 다 존재하고, PrintWriter 객체에서 write 메소드를 사용하는 경우 PrintWriter에서 정의한 메소드가 작동하는 것이죠.
이것을 잘 생각해보면, Writer에서는 write를 이렇게 정의했는데, PrintWriter에서는 그게 마음에 안들어서 기능을 바꾸고 싶을 수 있습니다. 그러면 새롭게 정의해 주면 됩니다.
메소드의 정의를 새롭게 덮어 씌운다고 해서 이것을 override, 혹은 오버라이딩이라고 합니다.
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
public class InstanceApp {
public static void main(String[] args) throws IOException {
PrintWriter p1 = new PrintWriter("result1.txt");
p1.write("Hello 1");
p1.close();
PrintWriter p2 = new PrintWriter("result2.txt");
p2.write("Hello 2");
p2.close();
p2.toString(); // Object의 메소드도 사용 가능!
}
}
API를 설명하는 페이지에 Tree라는 메뉴가 있습니다.
이 메뉴를 클릭해보면 Java에 있는 클래스들이 어떻게 상속되어 있는지를 트리 형태로 보여줍니다.
그리고 모든 트리의 중심은 바로 Object입니다.
모든 클래스는 Object로부터 상속받았다는 의미이죠.
이렇게 Object(객체)가 중심이 되는 언어가 Java이기 때문에, Java는 객체지향 프로그래밍 언어라고 부를 수 있는 것입니다.
이렇게 클래스, 인스턴스, 상속에 대해 알아봤습니다.
제가 처음 프로그래밍에 입문했을 때 정말 골치아팠던 개념들이기도 한데,
지금 이렇게 정리하면서 이해할 수 있다는게 참 신기하네요.
만약 이런 개념들이 익숙하지 않다고 해도 너무 걱정하지 않으셔도 됩니다.
하다보면 알아서 익숙해져요. (이 글을 보고 계신 분보다 머리가 뛰어나지 않은 저도 그랬습니다 ㅠㅠ)
그렇다면 다음 포스팅에서 뵙도록 하겠습니다!!!
오늘도 읽어주셔서 감사합니다 😊😊
최근댓글