<<<<<<<<<<constructor>>>>>>>>>>
Constructor(생성자)는 객체지향의 큰 그림을 지원하기 위해 필요한 메서드이다.
객체지향은 real world의 객체를 system화 하는 방법인데, 객체는 서로 다른 상태값을 갖는다.
쉽게 말하면 나 다르고 너 다르고 쟤도 다르다.
그러나 컴퓨터에서 인스턴스를 생성하면 같은 값이 나온다. 그리고 그 같은 값을 후에 다른 값으로 설정해줘야한다.
real world에서는 갓난아기때부터 다른 상태값을 갖는 것과는 대조적이다.
제대로 real world를 옮기지 못한다는 것 외에도 코딩에서 불편함이 있다.
만약에 2개의 인스턴스를 생성하고 이름을 바꿔주는 것은 어렵지 않지만 1000개의 인스턴스를 생성하고 이름을 바꾼다고 생각해보자. 이름을 바꿔주는 똑같은 코드가 1000줄이 적힐 것이다.
Constructor는 인스턴스 생성시부터 다른 상태값을 갖도록 지원해주는 방법, 메서드이다.
Constructor는 메서드의 일종이다. 그러나 메서드 시그니처(메서드 접근제한자, 반환타입, 메서드명, 전달인자)에는 반환타입이 있어야 하는데, 예외적으로 Constructor는 반환타입이 필요하지 않다.
그래서 Constructor에는 return type이 없다. 그리고 Constructor는 class이름과 같은 method명을 가져야 한다는 syntax규칙이 있다.
constructor는 new 키워드를 이용해 메모리에 적재해 인스턴스를 생성할 때에 호출된다.
Calculator cal = new Calculator();
에서 new 뒤에 있는 것이 생성자이다.
생성자는 .java파일을 컴파일함과 동시에 default생성자가 생겨난다.
생성자를 따로 타이핑하지 않았을 경우 default 생성자가 호출된다.
Bean class에서 필드를 구체적으로 만들지 않고 선언만 한 다음
다형성을 구현하기 위해 constructor 전달인자에 따라 필드값을 초기화해줄 수 있다.
이 때 사용하는 방법이 OverLoading이다.
Conductor 메서드, 생성자를 만들 때 같은 이름(클래스 이름과 같은 메서드)이고 다른 전달인자를 갖는 메서드를 여러 개 만들어서
new 키워드를 이용해 인스턴스를 만들 때 입력되는 값에 따라 생성 시 초기화(값을 처음 setting 해주는 작업)를 다르게 해 주는 것이다.
사용자가 초기화를 해주지 않고 출력하게 되면 자동 초기화 된 값이 출력되는데, 숫자를 받는 Data type의 경우에는 0으로, boolean 데이터 타입은 false로, Reference Data Type은 null로 된다.
객체가 서로 다른 상태를 갖는 real world를 constructor method를 overloading해서 구현했다.
객체지향의 요소를 빼고 문법적 요소만 본다면, constructor method를 이용해서 초기화 메커니즘을 제공해준다고 할 수 있다.
<<<<<<<<<공유>>>>>>>>>
객체지향의 개념에는 "공유"가 있다. 공유를 자바에서 구현하려면 extends라는 키워드를 사용하면 된다.
클래스 이름에
public class A extends B라고 되어있으면
B클래스를 확장해서 A클래스를 만들었다
라고 해석하면 된다.
이 때 A클래스에서는 B클래스의 필드와 메서드를 사용할 수 있는데(공유), 그 원리는 다음과 같다.
A클래스의 default생성자로 인스턴스를 생성하자.
A a = new A();
작업 순서)
a라는 변수를 하나 만듦
new를 이용, A클래스의 인스턴스를 새로 만든다.
생성된 A클래스인스턴스 참조값을 a에 대입한다.
주의할 점이 있다. A클래스의 인스턴스를 만들기 전에(A클래스 생성자를 실행하기 전에) 공유되는 B클래스의 생성자가 먼저 실행된다.
즉 new로 A클래스 인스턴스 만들기 == B클래스 생성자 실행해서 B클래스 인스턴스 만들고 이를 포함하는 A클래스 인스턴스를 만든다.
는 것이다.
다르게 말하면 extends로 클래스 간 hiarachy 구조이면 B클래스 constructor를 먼저 호출하고 A클래스 constructor를 호출한다는 것이다.
정보에 접근할 때에는 다음과 같다.
B라는 클래스 필드에 String name;이 있다고 하자.
a.getName을 하면 컴퓨터는 A클래스에 먼저 가서 getName을 찾는다. 그리고 없으면 상속해준 클래스 B에 가서 getName을 찾는다.
자바는 이렇게 공유 개념을 지원한다.
만일 과정 중에 cannot find symbol이라는 오류가 떴다면 다음의 과정이 일어난 것이다.
a.getName을 찾으러 A클래스에 갔는데 getName이 없다. 그래서 상속해준 B클래스에 가서 getName을 찾는데 없다. 다찾았는데 없다. 오류: 찾을 수 없습니다.
실생활에서는 "오타났네"라고 하면 된다.
<<<<<<<공유 키워드 super, this>>>>>>>>>
<<<<<super method, this method>>>>>>>>
앞서 new로 A클래스 인스턴스 만들기 == B클래스 생성자 실행해서 B클래스 인스턴스 만들고 이를 포함하는 A클래스 인스턴스를 만든다.
고 했다.
그 이유는 A클래스의 constructor method 첫 줄에 super(); 메서드가 생략되어 있기 때문이다.
super method는 상위 생성자를 호출하는 메서드이다.
super()는 상위의 default생성자를, super("~~")이라면 상위의 String 하나를 받는 생성자를 호출한다.
this는 현재 클래스의 생성자를 호출하는 메서드이다.
this(); 는 현재 클래스의 default생성자를, this(1); 이라면 현재 클래스의 int 하나를 인자로 받는 생성자를 호출한다.
아무것도 손대지 않고 인스턴스를 생성한다면 default 생성자에 의해 상위 default 생성자를 호출하고 현재 클래스의 default 생성자를 호출해 인스턴스를 만들겠지만,
super메서드와 this메서드를 이용하면 인스턴스 생성 시 메모리에 등재되는 과정에 관여할 수 있다.
이 때 주의할 점은 재귀적 오류가 발생하지 않도록 하는 것이다.
생성자 안에서 무한반복이 일어나지 않도록 주의하자.
또한 생성자에서 super나 this 메서드를 사용할 때에 생성자 메서드의 "첫 줄"에 super 메서드 혹은 this 메서드 "하나만" 사용할 수 있다.
또 만일 어떤 생성자도 만들지 않았다면 컴파일 시 자동으로 default 생성자가 만들어지지만, 하나라도 다른 생성자를 만들게 되면 default생성자는 자동으로 만들어지지 않는다.
생각보다 많은 경우에 default 생성자를 고려하지 못해서 오류가 난다고 하니 default 생성자를 JRE에 의존하지 말고 직접 만드는 습관을 갖는 것이 좋다.
(cf. 클래스에서 필드를 선언할 때
String name, phoneNum;
과 같이 데이터타입을 하나만 정의하고 CSV ,를 이용해 변수를 여러개 선언할 수 있다.
그러나 실제로는 아무도 이렇게 코딩하지 않으니 가능하다는 것만 알아두면 좋겠다.)
<<<<<<<<<<<<overriding>>>>>>>>>>>>>>>>
앞서 한 오버로딩처럼 오버라이딩 역시 다형성을 지원하는 방법이다.
하위 클래스의 생성자를 이용하면 생략되어있는 super(); 메서드로 인해 상위클래스의 default생성자가 먼저 호출되고 하위 클래스의 생성자가 호출된다고 했다.
그리고 필드나 메서드에 접근할 때에는 자신이 속해 있는 클래스에서 먼저 해당 필드나 메서드를 찾고 없으면 상위 클래스에 가서 찾는다고 했다.
이로 인해 만일 상위 클래스에 mmm라는 이름의 메서드가 있고, 하위 클래스에도 mmm라는 이름의 메서드가 있다면 컴퓨터는 자신이 속해있는 클래스에 해당 메서드가 있는지 찾아보고 없으면 상위로 넘어간다 했으니 하위클래스에 있는 mmm메서드가 호출되겠다.
오버라이딩은 이와 같이 공유 클래스에 있는 필드 혹은 메서드의 이름과 같은 이름을 사용해서 상위 클래스에 있는 필드 혹은 메서드가 아니라 현재 자신에게 있는 필드나 메서드를 호출하는 것이다.
오버라이딩의 사용은 다음과 같다.
예를 들어, 핸드폰1에 여러 기능이 있는데 기능A에 버그가 있다고 생각해보자. 그리고 후속 핸드폰2을 낼 때에 핸드폰1에 있는 기능은 다 넣되 문제가 발생한 기능A은 교체해서 넣겠다고 해보자.
이 때 핸드폰1의 기능A을 수정해서 공유하게 되면 원래 코드를 건드려야 하고, 이로 인해 예기치 못한 문제가 발생할 수도 있다.
만일 핸드폰 2를 만들 때 나머지 기능은 인스턴스를 생성해 공유받고, 기능A는 핸드폰1과 같은 이름의 다른 내용으로 핸드폰2 안에서 재정의한다면, 기능 A를 수행하라는 명령을 받았을 때에 핸드폰2에 있는 기능을 수행할 것이다.
따라서 오버라이딩은 공유된 클래스에 가지 않고 자신 안에 있는 같은 이름의 다시 만든 메서드를 호출하기 때문에 "재정의"라고 이해하면 좋다.
<<<<<<<<<<<<<<<<<<super, this reference>>>>>>>>>>>>>>>
객체지향은 reference로 접근해야 한다.
생성자를 이용해 인스턴스를 만들어보자.
Computer class를 Calculator class가 공유받고 있다.
Computer class
└▶Calculator class
Calculator cal = new Calculator();
이 때 만들어지는 과정은
cal이라는 이름의 변수를 선언하고, new로 메모리를 할당받고 Calculator생성자를 이용해 Computer인스턴스를 만들고 Calculator인스턴스를 확장하여 변수 cal에 넣는 게 끝이 아니었다.
변수 cal에 인스턴스 주소를 넣기 전에 this라는 reference와 super라는 reference가 시스템에 의해 만들어져서 확장하기 전 Computer 인스턴스를 super reference에, Calculator 인스턴스를 this reference에 주소값을 넣는다고 한다.
만약 오버라이딩을 이용해 Computer클래스에 있는 memory1 필드를 Calculator클래스에서 재정의했다면 memory1이라는 식별자만으로는 Computer클래스에 있는 memory1필드에 접근할 수 없다.
이 때 사용할 수 있는 것이 super, this reference이다.
super.memory1 이라고 하면 상위 클래스에 있는 memory1을, this.memory1이라고 하면 현재 클래스에 있는 momory1을 불러온다.
그리고 하나의 클래스에서 처음 변수를 선언한 후에 식별값 만으로 변수에 접근할 수 있었던 이유는 식별값만 코딩되었을 경우
this.식별값 으로 인식되기 때문이다.
this.은 생략할 수 있다.
또한 하나의 클래스에서 같은 이름의 변수가 두 개 있을 경우에
예를들어)
class Student
String name = "홍길동";
public string setName(String name){
name = name;
}
의 상황이라면, 전달인자로 들어온 name과 필드 name이 이름이 같다.
이 상황에서의 name은 가까이 있는 놈이라고 알아듣는다. 즉 전달인자로 들어온 name을 둘 다 가리킨다.
만일 대입연산자 앞의 name에 this.name이라고 입력해준다면 "홍길동"을 들어온 전달인자로 바꿔라 하는 설정을 하게 된다.
<<<<<<<<<<<<<<<package>>>>>>>>>>>>>>>
class path default는 .이라고 했었다. 하지만 . 뿐 아니라 C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar도 default class path 로 설정되어있다.
String을 보면 Camel case 표기법에 따라 대문자로 시작하는 클래스이다. 그러나 rt.jar에도 String class는 없다.
모든 .java 파일 맨 위에는 java.lang.* 이 생략되어있다.
.*는 "모두 다"라는 말이니 java안에 lang안에 있는 모든 것을 사용하겠다는 말이다. String은 여기에 있다.
윈도우에서는 폴더, 유닉스에서는 디렉토리라고 하는 파일이 들어있는 곳을 자바에서는 패키지라고 한다.
윈도우에서는 폴더를 역슬래시\로 구분하고, 유닉스에서 디렉토리는 슬래시/로 구분한다. 자바에서 패키지는 .으로 구분한다.
자바 패키지의 CSV는 .이다.
다시 String class가 있는 곳을 보면 java 패키지 안에 lang 패키지 안에 있는 것이다.
보면 패키지는 자신이 있는 위치를 알려주는 것이다.
만일 다른 패키지에 있는 클래스가 사용하고 싶을 때에는 import 키워드를 사용한다.
import java.util.Scanner;를 생각해보면,
자바 패키지 안에 유틸 패키지 안에 있는 스캐너 클래스를 import 들여오고 있구나 라고 해석할 수 있다.
앞서 클래스를 Application class와 Bean class로 구분했던 것은 "용도"에 따라 클래스를 구분한 것이다.
클래스는 누가 만들었느냐에 따라 구분할 수도 있다.
자바 개발환경을 사용하는 사용자(개발자)가 만든 클래스와 자바 개발환경을 개발한 Java진영에서 만든 클래스로 나눌 수 있다.
자바 진영에서 만든 클래스를 라이브러리(API를 모아놓은 것. 아직 API가 뭔지는 정확히 모른다)라고 한다.
'IT > 공부' 카테고리의 다른 글
[정보처리기사 필기] 도전 시작 (0) | 2022.02.02 |
---|---|
[프로그래밍] API, 접근제어자, static/instance, is a/has a관계 (0) | 2019.03.17 |
[프로그래밍] 객체지향, 메서드 문법, OverLoading, getter 메서드 (0) | 2019.03.17 |
[프로그래밍] call by value/reference, 배열, 객체지향 (0) | 2019.03.17 |
[프로그래밍] 연산자, 주석문, switch, for, while, 배열 (0) | 2019.03.04 |