코드의 재사용성이 높고, 유지보수가 용이하며, 중복 코드도 제거한다.
-> 빠른 변화를 쫓아갈 수 있다.
객체지향 언어 = 프로그래밍 언어 + 객체지향개념(규칙)
객체지향개념(규칙)은 반드시 외워두어야 한다.
4가지 핵심 개념
- 캡슐화
- 상속
- 추상화
- 다형성 (가장 중요!)
객체지향개념은 반복해서 공부할 수록 쉬워진다. -> 요약
자바의 정석 3판 보고, (핵심 + 응용)
바로 JSP, Spring을 배우자. (이해보다는 실습 먼저 하고, 만들어보고, 흉내내보고, 모든걸 해보자)
코딩 경험이 어느정도 쌓인 다음, 디자인패턴 / 객체지향 개념 기본서를 보자.
설계를 잘하려면 코딩 경험이 많아야 한다!
데이터 + 함수 결합 클래스
사용자 정의 타입
class Tv {
// 속성(변수)
String color;
boolean power;
int channel;
// 기능(메서드)
void power() {power = !power;}
void channelUp() {channel++;}
void channelDown() {channel--;}
}
위 코드를 통해 아래와 같은 객체가 생성됨
출처 : 자바의정석 남궁성님 유튜브
출처 : 자바의정석 남궁성님 유튜브
클래스 영역
클래스 영역 이외의 영역 - 메서드, 생성자, 초기화블럭 내부
class Variables
{
// 클래스 영역 -> 선언문만 가능 (변수 선언, 메서드 선언)
// 순서는 딱히 정해진 게 없다.
int iv; // 인스턴스 변수 "선언"
static int cv; // 클래스 변수 (static 변수, 공유 변수) "선언"
// 메서드 영역
void method(){ // 메서드 "선언" 및 정의
int lv = 0; // 지역 변수
}
}
class Card{
// iv : 개별 속성에 대해 사용
String kind; // 카드 무늬 (개별)
int number; // 카드 숫자 (개별)
// cv : 공통 속성에 대해 사용
static int width = 100; // 카드 폭 (공통)
static int height = 250; // 카드 높이 (공통)
}
Card c = new Card();
c.kind = "HEART";
c.number = 5;
// cv를 사용 할 때는, 참조 변수를 쓰기보다,
// 클래스 이름을 붙여주는게 일반적이다.
c.width = 200; -> Card.width = 200;
c.height = 300; -> Card.height = 300;
지역 변수(lv)는 반드시 수동 초기화 필수!! -> 0으로 자동 초기화 하게 두면, 메모리의 효율이 떨어짐. 지역 변수는 빨리 쓰고 빨리 버려서 없애야됨. 유지 기간이 짧음
멤버 변수(인스턴스 변수(iv), 클래스 변수(cv))는 유지기간이 비교적 길다. -> 자동 초기화가 된다.
자동 초기화
명시적 초기화 (=, 대입연산자 이용) : 간단한 초기화
ex-기본형 초기화) int door = 4;
ex-참조형 초기화) Engine e = new Engine(); // 객체 주소를 넣어주는 것이 초기화다
초기화 블럭 ({} 이용) : 복잡한 초기화
생성자 : 복잡한 초기화
클래스 변수 초기화 시점 : 클래스가 처음 로딩될 때(메모리에 올라갈 때) "단 한번"
인스턴스 변수 초기화 시점 : 인스턴스가 생성될 때 마다 (인스턴스가 만들어 질 때마다 iv가 새로 만들어지기 때문!)
InitTest it = new InitTest();
초기화 순서 (cv -> iv / 자동 -> 간단 -> 복잡)
1. 클래스 초기화 (자동 초기화 후, 간단 -> 복잡 초기화 진행)
2. 인스턴스 초기화 (자동 초기화 후, 간단 -> 복잡 초기화 진행)
3. 새로운 객체를 또 만들면, 클래스 초기화는 발생하지 않고, 새로운 객체만 초기화 된다
반환 타입 + 메서드 이름 ( 매개변수 선언 )
int add (int x, int y) { // 선언부
int result = x + y; // 구현부
return result;
}
// 매개변수 int x, int y와 메서드 내부의 int result는 지역변수(lv)다.
// 메서드 호출
public static void main (String[] args) {
int result = add(3, 5); // 메서드 호출
// 이 때, 넘겨주는 3, 5를 argument라고 한다.
// 3, 5가 add 메서드의 int x, int y로 넘어가게(대입) 되고, 계산이 처리된다.
// Argument는 "원본" 이고, Parameter는 "복사본"이다.
}
Static method : 메서드 앞에 "static"이 붙은 메서드
- 인스턴스 생성 없이, 항상 클래스이름.메서드이름() 으로 호출 가능
- ex : Math.random(), Math.round()
- 인스턴스 멤버와 관련 없는 작업을 하는 메서드
- 메서드 내에서 iv 사용 불가 (메서드를 호출했을 때, 객체가 있다는 보장이 없기 때문에 사용할 수 없다.)
- iv를 사용하지 않을 때, static을 붙이면 된다.
- 작업에 필요한 값을 parameter를 통해 전달받은 local variable로 해결하기 때문에, iv가 필요없다. iv가 필요 없기 때문에, 객체(인스턴스)의 생성이 필요가 없다.
- static 메서드는 인스턴스 메서드를 호출할 수 없다. (객체가 있다는 보장이 없음)
Instance method : 메서드 앞에 static이 "안"붙은 메서드
- 인스턴스 생성 후, 참조변수.메서드이름() 으로 호출
- 인스턴스 멤버(instance variable, instance method)와 관련된 작업을 하는 메서드
- 메서드 내에서 iv 사용 가능
- iv를 사용해야 하면, static을 붙이면 안된다.
- 작업에 필요한 값을 iv를 사용하기 때문에, 파라미터를 굳이 안 넘겨줘도 된다. 또한, iv를 사용해야 하므로 필수적으로 인스턴스가 생성 되어야 한다.
- 인스턴스 메서드는, 다른 인스턴스 메서드와 static 메서드를 호출할 수 있다.
위 두 메서드는 "인스턴스 변수(iv)" 사용 여부에 따라 분류됨.
객체, 인스턴스 = iv 묶음
한 클래스 안에 같은 이름의 메서드를 여러 개 정의하는 것
대표적 예시
void println()
void println(boolean x)
void println(char x)
void println(char[] x)
void println(double x) .... 등등
오버로딩 성립 조건
1. 메서드 이름이 같아야 한다.
2. 매개변수의 갯수 또는 타입이 달라야 한다.
3. 반환 타입은 오버로딩에 영향을 미치지 않는다.
- 오버로딩 예시
long add (int a, long b) { return a + b; }
long add (long a, int b) { return a + b; }
-> add(3, 3); 으로 실행하면, 사용해야 할 메서드가 1번인지, 2번인지 알 수가 없기 때문에 에러 남. (불명확. ambiguous)
인스턴스가 생성될 때마다 호출되는 "인스턴스 초기화 메서드" == iv 초기화 메서드
인스턴스 생성 시 수행할 작업(iv 초기화)에 사용
iv를 편리하게 초기화하려고 만듬
class Card {
// 생성자 오버로딩
Card() { // 매개변수 없는 생성자
// 인스턴스 초기화 작업
}
Card(String kind, int number) { // 매개변수 있는 생성자
// 인스턴스 초기화 작업
}
}
규칙
1. 생성자의 이름이 클래스 이름과 같아야 한다.
2. 초기화 메서드는 "대입"작업을 하는 대입문이기 때문에, 리턴 값이 없다. (void 안 붙임)
-> 항상 반환 값이 없기 떄문에 void를 붙이지 않음
3. 모든 클래스는 반드시 1개 이상의 생성자가 있어야 한다.
-> Card c = new Card(); 이 구문은 사실 "생성자 호출" 이었던 것!
-> 이는 "기본 생성자"라고 부른다. 컴파일러가 생성자가 없을 때 추가를 해줌!
기본 생성자 (Default constructor)
- 매개 변수가 없는 생성자
ex) Card() {}; // Card 클래스의 기본 생성자
- 생성자가 하나도 없을 때만, 컴파일러가 자동으로 추가 함.
- 왠만하면, 기본생성자를 "반드시" 만들어주자!
매개변수가 있는 생성자
- 초기화를 편리하게 하기 위해서 사용
- 코드를 간결하게 사용하기 위해서 사용
Car c = new Car("White", "auto", 4); 구현 순서
1. 참조변수 c 생성
2. new 연산자가 클래스를 보고, 객체를 생성
3. Car("White", "auto", 4) 생성자 호출 및 객체 초기화
4. 참조변수 c에 객체 주소 대입
생성자 this()와 참조변수 this는 서로 연관이 없음!