본문 바로가기
Language/Java

공부내용 정리 Java :: 입문II

by Cs.Woo 2021. 5. 6.

# 자바의 클래스란?

public class ClassApp {

	public static void main(String[] args) {
		
		// 클래스의 사용법에 대하여 알아보기.
		
		System.out.println(Math.PI); // pi에 대한 값이 출력 Math 클래스에 저장되어있는 변수를호출
		System.out.println(Math.floor(1.6)); // 1.0 내림 Math에 내장되어있는 floor라는 메소드를 호출함
		System.out.println(Math.ceil(1.6)); // 2.0 올림 Math 내에 내장되어있는 ceil이라는 메소드를 호출함
		
	
	

}

 자바에 있어서 클래스란, 간단히 개념만 서술할 때, 서로 연관되어 있는 변수 혹은 메소드를 모아서 거기에 이름을 붙힌 것이라고 할 수 있다. 

 가령 예제의 Math와 같이 수학에 관련된 메소드(함수)들이 옹기종기 모여있는 것을 Math 클래스 라고 일컫는다.

# 자바의 인스턴스란?

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
// import를 사용함으로써 PrintWriter라는 클래스는
// java의 io에 소속되어있다는 것을 이 프로그램에 알려주어야 한다.

public class InstanceApp {

	public static void main(String[] args) throws IOException {
		// result1.txt 파일에 글씨를 써서 저장하여 생성하는 기능
		PrintWriter p1 = new PrintWriter("result1.txt");
		// p1 result1 이라는 파일을 읽음(현재는 그파일 존재x) -> 예외발생
				// p1 변수에 담겨져있는 클래스로 생성된 어떠한
				// 그 무언가를 인스턴스라고 일컫는다.
		//p1 에는 PrintWriter 라는 클래스의 인스턴스만 들어간다는
		//의미로서 앞에 명시를 해주어야만 한다.
		//PrintWriter는 패키지를 불러오는 작업을 해야한다
		//그냥 임포트만 했을 경우엔 빨간줄이 있음
		// 이때는 파일이 없는데 어떻게 읽냐는 예외상황이 발생한 것
		p1.write("Hello 1");
		// p1에 hello 라고 작성함
		p1.close();
		// p1을 닫아줌
		
		PrintWriter p2 = new PrintWriter("result2.txt");
		p2.write("Hello 2");
		p2.close();
		
		// 결과 :: 선택한 프로젝트 디렉토리에 result1, result2가 생겨서 내용이 작성되어있음

	}

}

 new가 붙어있으면 p1에 PrintWriter라는 클래스를 통하여 "인스턴스"를 생성하여 저장한다는 뜻이다. 이렇게 클래스를 통하여 인스턴스를 생성하여 변수에 저장하면, 같은 클래스를 썼더라도 다른 내부적인 상태를 갖게된다. 현재 이해하고 있는 객체와 상당히 유사한 개념이다.

 Math와 같은 클래스는 일회성 클래스이다. 값을 내보내기 위한 클래스이기 때문에, 생성자라는 것이 따로 존재하지 않는다. 즉, 인스턴스를 생성할 필요가 없다는 의미이다.

 그러나 PrintWriter와 같은 클래스는 클래스 내부에 기능들이 꼬리에 꼬리를 물고 응용이 가능하기 때문에 생성자 라는 것이 존재하고 이 것은 인스턴스를 생성할 필요가 있다는 의미이다.

 

 

# 자바의 상속(Inheritance)

 현재 예제에서 다루고 있는 PrintWriter라는 클래스(java.io.PrintWrite)를 보면 상위 항목에 Writer(java.io.Writer)가 있는 것을 확인할 수 있다. 이때, 우리는 PrintWriter의 부모 클래스로  Writer라고 하고, 자식 클래스로 PrintWrite라고 한다. 마찬가지로, Writer의 상위 항목에는 Object(java.lang.Obejct)라는 상위 항목이 있다. 이역시 Writer의 부모클래느는 Object가 되고, Object의 자식클래스는 Writer가 된다고 이야기 한다.

 이때 Writer는 Obejct를 상속받았고(자식클래스), PrintWrite는 Writer를 상속받았다(자식클래스)라고 표현한다. 어떠한 기능을 만들고자 할 때 겹치는 기능이 있는데 새로운 기능을 하나 추가하자고 기존의 기능까지 전부 다시 만들기란 복잡하며 비효율적인 일이 된다.

 따라서 PrintWriter라는 클래스를 만들고자 한 사람은 Writer의 기능을 그대로 물려받으면서(상속받으면서) 새로운 기능만 추가할 수 있도록 조치한 것이다. 이것이 바로 상속의 개념이다. 상위의 Object와 Writer도 마찬가지이다.

 하기의 예제는 PrintWrite가 어떠한 상속관계를 갖고 있는지에 대한 것을 알 수 있는 예제이다.

 

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
// import를 사용함으로써 PrintWriter라는 클래스는
// java의 io에 소속되어있다는 것을 이 프로그램에 알려주어야 한다.

public class InstanceApp {

	public static void main(String[] args) throws IOException {
		
		PrintWriter p1 = new PrintWriter("result1.txt");
		// PrintWriter에서 오른쪽마우스를 클릭하면
		// Hierarchy라는 버튼이 있다.
		// 이것을 클릭하면 해당되는 클래스의 상속관계를 확인할 수 있다.
		
		p1.write("Hello 1");
		p1.close();
		
		PrintWriter p2 = new PrintWriter("result2.txt");
		p2.write("Hello 2");
		p2.close();
	

	}

}

 PrintWriter의 상속관계를 확인해보면, 최상위 클래스인 Object에 toString()이라는 메소드가 존재한다는 것을 알 수 있다. PrintWrite는 Writer를, Writer는 Object를 상속하였기 때문에 굳이 Object를 Import(불러오기)를 하지 않아도 PrintWrite만으로도 toString()을 사용할 수 있게 된다. 이것이 바로 상속의 기능이다.

 

 모든 클래스는 Object라는 클래스를 상속받는다. 모든 클래스의 상위에는 Object가 존재하는 것이다(자바에 내장되어있는 클래스).

 그렇다면 만일 Writer라는 기능을 만들고자 할 때는 필연적으로 Object를 상속받도록 될텐데, 그것을 다음과 같이 표현한다. 

"Writer extends Obejct"

 오브젝트를 확장하여 Writer를 만들었다 라는 의미가된다.

 

 예제에서, 가령, PrintWrite p1 = new PrintWriter("result1")일 때, p1.toString()을 한다면, 자바는 우선적으로 PrintWriter에서  toString()의 존재 유무를 검사한다. 그리고 발견되지 않았다면 상위 클래스(부모클래스)인 Writer에 가서 존재 유무를 검사한다. 그 후 역시 발견되지 않았다면 다시 상위클래스인 Object로 가서 재 검사를 하는 방식으로 동작하고 있다. 이 방식으로 검사를 진행하다, 최상위 클래스 역시 해당 메소드를 발견하지 못한다면, 오류를 발생하게 된다.

 

 그리고 동일 예제에서, Writer에도 wrtie()라는 메소드가 A기능으로 존재하고, Writer를 상속받은 PrintWrite에도 write()라는 메소드가 B기능으로 존재할 때, PrintWrite에서 write()메소드를 사용했다면, 이는 Wirte의 write()[기능A]로서 사용된 것이 아니라 PrintWrite의 write()[기능B]로서 사용되게 된다.

 

 이는 Writer 를 상속하여 PrintWrite라는 클래스를 만든 사람이, Writer라는 기능을 모두 물려받긴 했지만 이름은 같고 자신의 취지와는 메소드가 존재할때, 동일한 이름에 다른 기능을 덮어씌워서 사용하게 하는 것이 가능하다는 의미이고 이를 덮어씌웠다는 의미의 단어인 오버라이드(Override)라고 일컫는다.