여섯째날 [클래스(1)]
목차
1. 객체 지향 프로그래밍
2. 객체(Object)와 클래스(Class)
3. 클래스 선언
4. 객체 생성과 클래스 변수
5. 클래스의 구성 멤버
6. 필드(Field)
7. 생성자(Constructor)
[1] 객체 지향 프로그래밍
* OOP : Object Oriented Programming
* 부품 객체를 먼저 만들고 (클래스를 만든다) + 그것들을 조립해 완성된 프로그램을 만드는 기법
* 클래스를 만들어서 동작하되, 여러 클래스를 만들어 조립해서 만들어가는 프로그램
* 객체(Object)
- 물리적으로 존재하는 것 (자동차, 책, 사람 ...)
- 추상적인 것 중에서 속성과 동작을 가지는 모든 것
- 객체는 필드(속성, 변수)와 메소드(동작)로 구성된 자바 객체로 모델링 가능
* 객체의 상호 작용 : 객체들은 서로 연관성이 있고, 상호작용 할 수 있음
- 사람 ↔️ 계산기 : 서로 간 기능(동작)을 이용하고 데이터를 주고 받는다.
- 대신, 객체를 생성해야 활용 가능
* 객체간의 관계
- 사용 관계 : 객체가 다른 객체를 사용하는 관계 (사람이 자동차를 사용)
- 상속 관계 : 종류 객체와 구체적인 사물 객체 관계 (자동차는 기계 안에 있는 내용을 상속 받는다 = 기계 안의 모든 내용이 자동차 안에 있다)
- 집합 관계 : 완성품과 부품의 관계 (일대다의 관계, 자동차 객체는 엔진.타이어.핸들 객체인 부품들과 관계됨)
* 객체 지향 프로그램의 특징
- 캡슐화 : 실제 구현 내용을 감춘다
- 상속 : 부모 객체의 필드와 메소드를 자식 객체에게 물려주는 행위. 자식은 기능을 더 추가해서 확장 가능
- 다형성 : 같은 타입이지만 실행 결과가 다양한 객체를 대입할 수 있음 (하나의 자동차에도 여러 종류의 타이어 가능)
[2] 객체와 클래스
* 객체(Object)와 클래스(Class)
- 현실의 설계도 = 자바 클래스
- 클래스에는 객체를 생성하기 위한 필드와 메소드가 정의됨
- 클래스로부터 만들어진 객체를 해당 클래스의 인스턴스 라고 말함
- 객체 = 인스턴스 : 인스턴스는 내가 만든 클래스에 있는 변수가 메소드가 '힙 메모리'에 올라가는 상태를 말함. 즉 조금은 다르지만, 편하게 같다고 말해도 상관X
- 하나의 클래스로부터 여러 개의 인스턴스를 만들 수 있음 : 여러개의 객체가 가능하다는 소리.
- 클래스 : 내가 하고 싶은 것들을 기능상으로 넣어줌. 잘 만든 클래스는 객체를 생성하여 사용하면 됨
[3] 클래스 선언
* 클래스 이름 정하기
* 클래스 소스 파일 생성 : "클래스이름.java"
* 클래스 선언
public class 클래스이름{
}
일반적으로 소스 파일 당 하나의 클래스를 선언. 하지만 두 개 이상의 클래스 선언도 가능. 대신 파일 이름과 똑같은 클래스에만 public을 붙여줘야 함
소스파일이 Car.java라면
public class Car{
}
class Tire {
}
[4] 객체 생성과 클래스 변수
* 클래스 선언하고 컴파일 했다면, 객체를 생성할 설계도가 만들어진 것
* 클래스로부터 객체를 생성하는 방법
new 클래스();
'new' : 클래스로부터 객체를 생성시키는 연산자.
new + 생성자 = new + 클래스()
생성자 : 클래스() 형태
new 연산자로 생성된 객체는 메모리 힙(heap) 영역에 생성됨 ➡️ 객체의 주소를 리턴함 ➡️ 참조 타입인 클래스 변수에 저장 : 변수를 통해 객체 사용 가능
* 클래스 타입으로 선언된 변수에 new 연산자가 리턴한 객체의 주소를 저장하는 코드 : 2줄 또는 1줄로 가능
클래스 변수;
변수 = new 클래스();
클래스 변수 = new 클래스();
클래스는 하나여도, new 연산자를 사용한 만큼 객체가 메모리에 생성된다.
이러한 객체가 클래스의 인스턴스들이다.
같은 클래스로부터 생성되더라도, 객체들은 자신만의 고유 데이터를 가지게 된다.
* 클래스의 용도
- 라이브러리(API : Application Program Interface)용 : 자체적으로 실행되지 않음, 다른 클래스에서 이용할 목적으로 만든 클래스
- 실행용 : main()메소드를 가지고 있는 클래스. 실행할 목적으로 만든 클래스
- 대부분의 객체 지향 프로그램은 라이브러리와 실행 클래스가 분리되어 있음
1개의 애플리케이션 = (1개의 실행클래스) + (n개의 라이브러리 클래스)
[5] 클래스의 구성 멤버
필드(Field)
생성자(Constructor)
메소드(Method)
클래스 구성 멤버 = 멤버 변수 = 필드,생성자,메소드 = 전역변수 = 글로벌변수
: 클래스 블럭에 만드는 것, 객체를 만드는 것에 쓰이는 멤버들, 힙메모리에 올라가는 변수들
로컬 변수 = 지역 변수 : 메소드 블럭에 만드는 변수
[6] 필드(field)
* 필드의 내용 : 저장하는 데이터들
- 객체의 고유 데이터
- 객체가 가져야 할 부품 객체
- 객체의 현재 상태 데이터
타입 필드 = 초기값;
String company = "현대자동차";
String model = "그랜저";
int maxSpeed = 300;
int productionYear; //초깃값 설정하지 않아도 됨
* 필드의 기본 초기값 : 초기값이 지정되지 않은 필드. 객체 생성 시 자동으로 기본값으로 초기화.
* 필드 사용 : 필드값을 읽고, 변경하는 작업
* 필드 사용 객체 내부 : "필드이름"으로 접근
- 같은 클래스 내부라는 뜻. 힙 메모리 안(같은 메모리 안)에 필드, 생성자, 메소드가 생성되기 때문에 그냥 필드이름 바로 써서 접근 가능
객체 내부
//필드
int speed;
//생성자
Car(){
speed = 0;
}
//메소드
void method(...){
speed = 10;
}
* 필드 사용 객체 외부 : "변수.필드이름"으로 접근
- 남의 클래스를 쓸때니까, 객체 생성하고 난 후 "변수.필드이름" 써서 접근해야 함
void method(){
//Car 객체 생성
Car myCar = new Car();
//필드 사용
myCar.speed = 60;
}
* main()은 static이 붙었기 때문에, 메소드 영역에 저장됨 : 바로 필드를 사용할 수 없고 접근 불가. 사용하려면 객체를 생성하는 수 밖에
[7] 생성자 (Constructor)
* 생성자 : new 연산자에 의해 호출되어 객체의 초기화 담당
new 클래스();
- 필드의 값을 설정
- 메소드를 호출해 객체를 사용할 수 있도록 준비하는 역할을 수행함
- 생성자를 실행시키지 않으면 클래스로부터 객체를 만들 수 없다.
- 생성자 이름 : 언제나 클래스 이름과 똑같음
- 메소드와 비슷하게 생겼지만, 리턴 타입이 없고, 클래스 이름으로 되어 있다.
* 기본 생성자 (Default Constructor)
- 모든 클래스는 생성자가 반드시 존재함. 하나 이상 가질 수 있음.
- 생성자 선언을 생략하면 컴파일러는 기본 생성자 추가 : public 클래스 () { }
- 클래스에서 생성자를 선언하지 않아도, new 연산자 뒤에 기본 생성자를 호출해서 객체를 생성시킬 수 있음 : 색칠된게 기본 생성자
Car myCar = new Car();
- 클래스에 명시적으로 선언한 생성자가 한 개라도 있으면, 컴파일러는 기본 생성자를 추가하지 않음.
* 생성자 선언
- 기본 생성자 대신 개발자가 직접 선언하는 경우
클래스 (매개변수선언, ...){
//객체의 초기화 코드
}
- 객체의 초기화 코드 : 필드에 초기값 저장, 메소드를 호출해 객체 사용 전에 필요한 준비를 함
- 매개 변수 선언 : 생략 가능, 또는 여러 개 선언 가능
- new 연산자로 객체를 생성할 때, 개발자가 선언한 생성자가 있으면 반드시 사용한다.
* 필드 초기화
- 클래스로부터 객체가 생성될 때 필드는 기본 초기값으로 자동 설정됨
- 다른 값으로 초기화하고 싶을 때 방법 (1) 필드를 선언할 때 초기값을 주는 방법 : 동일한 클래스로부터 생성되는 객체는 모두 같은 데이터 갖게 됨
<Korean 클래스에 nation 필드를 선언하면서 "대한민국"으로 초기값을 준 경우, Korean 클래스로부터 k1과 k2 객체를 생성하면 k1과 k2 객체의 nation 필드에는 모두 "대한민국"이 저장되어 있음>
public class Korean{
String nation = "대한민국";
String name;
String ssn;
}
Korean k1 = new Korean();
Korean k2 = new Korean();
- 다른 값으로 초기화하고 싶을 때 방법 (2) 생성자의 매개값으로 초기값 설정 : 외부에서 제공되는 다양한 값으로 초기화 할때. 이름(name)과 주민번호(ssn) 필드값은 클래스를 작성할 때 초기값을 줄 수 없다. 객체 생성 시점에 다양한 값을 가져야 하기 때문.
따라서 생성자의 매개값으로 값들을 받아 초기화 한다.
public class Korean{
//필드
String nation = "대한민국";
String name;
String ssn;
//생성자
public Korean(String n, String s){
name = n;
ssn = s;
}
}
Korean k1 = new Korean("박자바", "012345-6789012")
Korean k2 = new Korean("김자바", "012345-2948571")
"박자바", "김자바"는 매개 변수 n을 통해 전달되고, 주민번호는 매개 변수 s를 통해 전달됨. 이 값들은 각각 name 필드와 ssn 필드의 초기값으로 사용됨
* 매개 변수와 필드명이 같은 경우 this 사용
- 매개 변수 이름이 너무 짧으면 코드의 가독성이 좋지 않음. 관례적으로 필드와 동일한 이름을 갖는 매개 변수를 사용
따라서 "this.필드"로 사용해야 함.
- this : 객체가 객체 자신을 this라고 함. this라는 참조 변수로 필드를 사용하는 것과 동일함
* 생성자 오버로딩 : 매개변수의 타입, 개수, 순서가 다른 생성자 여러 개 선언 가능
- 이유 : 객체를 생성할 때 외부 값으로 객체를 초기화할 필요가 있음. 외부 값이 어떻게 제공될지 모르니 생성자도 다양화 해야 한다는 것
* 다른 생성자 호출 : this()
- 생성자 오버로딩 시, 생성자 간의 중복된 코드가 발생함. 초기화 내용이 비슷한 생성자들에서 이런 현상을 많이 볼 수 있음
➡️ 초기화 내용을 한 생성자에 몰아서 작성한 후, 다른 생성자는 전부 다 적은 생성자를 this(...)로 호출한다.
- this()는 자신의 다른 생성자를 호출하는 코드
- 반드시 생성자의 첫줄에서만 허용됨
Car(String model, String color, int maxSpeed){
this.model = model;
this.color = color;
this.maxSpeed = maxSpeed;
}
Car(String model){
this(model, "은색", 250);
}
Car(string model, String color){
this(model, color, 250)
}
[8] 메소드
메소드 : 객체의 동작(기능) / 호출해서 실행할 수 있는 중괄호{} 블록 / 메소드 호출하면 중괄호 {} 블록에 있는 모든 코드들이 일괄 실행 / 다른 객체를 생성해서 다양한 기능을 수행하기도 함 / 객체 간의 데이터 전달 수단으로 사용 / 외부로부터 매개값을 받을 수도 있고, 실행 후 어떤 값을 리턴할 수도 있음
[8.1] 메소드 선언
리턴타입 메소드이름 ([매개변수선언, ...]){
//실행할 코드 작성
}
* 리턴타입 : 메소드가 실행 후 리턴하는 값의 타입, 있을 수도 있고 없을 수도 있음
- void : 리턴 안함
- 기본 데이터 타입 8개 & 모든 클래스 올 수 있음
* 메소드이름 : 내맘대로, 자바 식별자 규칙에만 맞게 쓰면 됨
* 매개 변수 선언 : 메소드가 실행할 때 필요한 데이터를 외부에서 받기 위해 사용. 필요 없을 수도 있음
메소드 선언
void powerOn(){...}
double divide(int x, int y){...}
메소드 호출
powerOn();
double result = divide(10, 20);
혹은 이렇게 표현
byte b1 = 10;
byte b2 = 20;
double result = divide(b1,b2)
* 매개 변수의 수를 모를 경우
(1) 매개 변수를 배열 타입으로 선언 : 대신 메소드 호출 전 배열 생성해야 함
int sum1(int[] valeues) { }
(2) 값의 리스트만 넘겨줌 . 매개변수를 "…"를 사용해서 선언 : 메소드 호출 시 넘겨 준 값의 수에 따라 자동으로 배열이 생성되고 매개값으로 사용
[8.2] 리턴문
* 메소드 실행을 중지하고 리턴값 지정
* 리턴값이 있는 메소드 : 반드시 리턴문 사용해 리턴값 지정할 것 : return문 뒤에 실행문 올 수 없음
* 리턴값이 없는 메소드 : 메소드 실행을 강제 종료 시키는 역할
* 메소드 호출
- 내부 : 메소드 이름으로 호출
- 외부 : 객체 생성 후, 참조 변수를 이용해 호출
* 메소드 오버로딩 : 매개변수의 타입, 개수, 순서가 달라야 함