-
Notifications
You must be signed in to change notification settings - Fork 1
Day 11(21.09.15)
※들어가기에 앞서
수업의 내용대로 정리를 하고 있기에 순서가 앞뒤로 오락가락할 수 있음. 예를들어 앞에서 메소드 얘기를 먼저 해놓고 갑자기 OOP 얘기를 시작한다는 것처럼...
현실 세계에서는 어떤 제품을 만들 때, 별개의 부품을 따로 개발하고 이를 조립하는 과정을 통해 제품 하나를 완성한다. 이와 마찬가지로, 소프트웨어를 개발할 때에도 부품에 해당하는 객체들을 먼저 만들고 이 객체들을 조립해서 프로그램을 완성하는 기법이 있는데, 이를 객체 지향 프로그래밍(Object Oriented Programming)이라고 한다.
객체의 정의는 물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신의 속성을 가지고 있고, 다른 것과 식별 가능한 것을 말한다. 쉽게 말하면 우리 주변에 있는 모든 것들이 전부 객체가 될 수 있다. 객체는 속성과 동작으로 구성되어 있는데, 예를 들면 자동차의 경우 색상, 모델과 같은 속성이 있고, 달린다는 동작이 있다. 자바에선 이러한 속성과 동작을 필드와 메소드라고 부른다.
현실에서 객체는 설계도를 바탕으로 만들어진다. 자동차를 예로 들면, 사람들이 자동차를 이용하기 위해서는 공장에서 설계도를 보고 자동차를 만들어야 한다. 이는 OOP에서도 마찬가지다. 메모리에서 사용하고 싶은 객체가 있다면 설계도로 해당 객체를 만드는 작업이 필요한데, 이때 필요한 설계도의 개념이 자바에서는 클래스라는 것이다. 클래스에는 객체를 생성하기 위한 필드와 메소드가 정의되어 있는데, 클래스로 만들어진 객체를 해당 클래스의 객체(인스턴스)라고 한다. 그리고 이 클래스에서 객체를 만드는 과정을 객체화(인스턴스화)라고 한다. 자동차에서도 하나의 설계도로 여러 자동차를 만들 수 있듯이, 자바에서도 하나의 클래스에서 여러 개의 객체(인스턴스)를 생성할 수 있다.
클래스를 사용하기 위해선 먼저 클래스를 선언해야 하는데, 이때 클래스의 이름은 다른 클래스와 식별될 수 있도록 하는 것이 중요하므로 식별자 작성 규칙에 따라서 만들어야 한다.
- 하나 이상의 문자로 작성할것.
- 첫 번째 글자에는 숫자가 올 수 없다.
- '$', '_' 외의 특수 문자는 사용할 수 없다.
- 자바 키워드는 사용할 수 없다.
- 자바 언어는 영어 대소문자를 구분한다. 관례적으로는 클래스의 첫 글자는 대문자를 사용한다.
클래스를 선언하고 컴파일했다면 이제 객체를 생성할 설계도가 만들어진 것이다. 여기서 이 설계도인 클래스를 바탕으로 객체를 생성하려면 다음과 같이 new 연산자(생성자)를 사용하면 된다.
new 클래스명();new는 클래스로부터 객체를 생성시키는 연산자이다. new 연산자 뒤에는 생성자가 오는데, 생성자는 클래스명() 형태를 하고 있다. new 연산자로 생성된 객체는 메모리 영역 중에서도 heap 영역에 생성되는데, 현실에서도 물건을 놓은 위치를 모르면 물건을 사용할 수 없듯이 자바의 객체도 마찬가지이다. 그래서 new 연산자는 heap 영역에 객체를 생성시킨 후, stack 영역에 객체의 주소를 리턴하도록 되어 있다.
다음 프로그램은 Student 클래스를 선언하고 StudentExample 클래스의 main() method에서 Student 객체를 생성하는 과정을 나타낸 프로그램이다.
//Student.java
public class Student{
}//StudentExample.java
public class StudentExample {
public static void main(String[] args) {
Student s1 = new Student();
System.out.println("s1 변수가 Student 객체를 참조합니다.");
Student s2 = new Student();
System.out.println("s2 변수가 또 다른 Student 객체를 참조합니다.");
}
}result
s1 변수가 Student 객체를 참조합니다.
s2 변수가 또 다른 Student 객체를 참조합니다.예제가 실행되면 stack 메모리와 heap 메모리에 각각 클래스 변수와 객체가 생성된다. Student 클래스는 하나지만 new 연산자를 사용한 횟수만큼 객체가 메모리에 생성된다. 이러한 객체들은 Student이 인스턴스들이다. 같은 클래스에서 생성되었어도 각각의 Student 객체는 자신만의 고유 데이터를 가지면서 메모리에서 활동하게 된다. 즉, s1이 참조하는 Student 객체와 s2가 참조하는 Student 객체는 완전히 독립된 서로 다른 객체라는 뜻이다.
클래스에는 객체가 가져야할 구성 멤버가 선언된다. 구성 멤버에는 필드(Field), 생성자(Constructor), 메소드(Method)가 있다. 이 구성 멤버는 생략되거나 여러개 작성될 수 있다.
public class ClassName {
//field : 객체의 데이터가 저장되는 곳
int fieldName;
//constructor : 객체 생성 시 초기화 역할 담당
ClassName() { ...}
//method : 객체의 동작에 해당하는 실행 블록
void methodName() {...}
}객체의 고유 데이터, 부품 객체, 상태 정보를 저장하는 곳이다. 선언 형태는 변수와 비슷하지만 필드를 변수라고 부르지는 않는다. 변수는 생성자와 메소드 내에서만 사용되고 생성자와 메소드가 실행 종료되면 자동으로 소멸된다. 반면, 필드는 생성자와 메소드 전체에서 사용되며 객체가 소멸되지 않는 한 계속 존재한다.
생성자는 new 연산자로 호출되는 특별한 중괄호 {} 블록이다. 생성자의 역할은 객체 생성시 초기화인데, 필드를 초기화 하거나, 헤소드를 호출해서 객체를 사용할 준비를 한다. 메소드와 비슷하게 생겼지만 클래스 이름으로 되어 있고, 리턴 타입이 없다.
메소드는 객체의 동작에 해당하는 중괄호 {} 블록을 말한다. 이 중괄호 블록의 이름이 메소드의 이름이 된다. 메소드를 호출하면 중괄호 블록 안에 있는 모든 코드들이 일괄적으로 실행되는데, 필드를 읽고 수정하는 역할도 하지만, 다른 객체를 생성해서 다양한 기능을 수행하기도 하며, 객체 간의 데이터 전달의 수단으로도 사용된다.
필드는 객체의 고유 데이터, 객체가 가져야할 부품 등의 데이터를 저장하는 곳이다. 자동차 객체가 있다고 가정할때, 제조사, 모델, 색깔 등은 고유 데이터에 해당하고, 현재 속도, 엔진 RPM 등은 상태 데이터에 해당하며, 차체, 엔진, 타이어는 부품에 해당한다 볼 수 있다. 따라서 해당 데이터들은 자동차의 클래스를 설계할 때 필드로 선언되어야 한다.
public class Car {
//자동차 클래스 선언
String company;
String model;
String color;
int maxSpeed;
// 고유 데이터
int speed;
int rpm;
// 상태
Body body;
Engine engine;
Tire tire;
// 부품필드 선언은 클래스 중괄호 블록 어디서든 가능하다. 하지만 생성자와 메소드의 중괄호 블록 내부에서는 선언될 수 없다. 생성자와 메소드의 중괄호 블록 내부에 선언된 것은 전부 로컬 변수로 취급되어 다른 블록에서 사용할 수 없게 된다. 필드 선언은 변수의 선언과 비슷하기 때문에 필드를 클래스 멤버 변수라고 부르기도 한다. (권장하지는 않음) 선언 할때는 아래와 같이 선언한다.
타입 필드 = 초기값;
타입에는 기본 타입, 참조 타입이 모두 올 수 있으며, 초기화는 생략 가능하다.
필드 사용의 의미는 필드값을 읽고 변경한다는 것을 말한다. 클래스 내부의 생성자나 메소드에서 사용할땐 단순히 필드 이름으로 읽고 변경하면 되지만 외부에서 사용할 경우엔 클래스로부터 객체를 생성한 뒤에 필드를 사용해야 한다. 그 이유는 필드는 객체에 소속된 데이터이기 때문이다. 따라서 객체가 존재하지 않는데 필드가 존재할 수 없다.
public class WhoseCar
void method() {
Car myCar = new Car();
// Car 객체 생성
myCar.speed = 60;
// 필드 사용
}public class Car
//field
int speed;
//constructor
Car() {
speed = 0;
}
//method
void method(...) {
speed = 10;
}위 예시에서 Car 클래스의 speed 필드는 생성자와 메소드에서 변경이 가능하다. 사용 방법은 변수와 동일하지만 차이점은 변수는 자신이 선언된 블록 내부에서만 사용할 수 있지만 필드는 생성자와 모든 메소드에서 사용할 수 있다. 외부 클래스인 WhoseCar 클래스에서 Car 클래스의 필드인 speed를 사용하려면 Car 객체를 먼저 생성해야 한다.
myCar 변수가 Car 객체를 참조하게 되면 도트(.) 연산자를 사용해 speed 필드에 접근할 수 있게 된다.
- 다음은 강아지의 정보를 출력해주는 프로그램을 작성한 것이다.
//Dog.java
public class Dog {
// field 선언
String name;
int age;
double weight;
//기능 method
void bark() {
System.out.println("멍멍");
}
//강아지의 정보 출력
void printInfo() {
System.out.println(name);
System.out.println(age);
System.out.println(weight);
}
}public class WhoseDog {
public static void main(String[] args) {
//강아지 한마리 객체 생성
Dog dog1 = new Dog(); //Dog 객체를 참조하는 참조변수 dog1
dog1.name = "초코";
dog1.age = 3;
dog1.weight = 3.5;
// Dog 클래스의 필드에 정보 저장
dog1.printInfo();
// 정보를 출력하는 메소드 printInfo() 실행
}
}result
초코
3
3.5
-
다음은 자동차의 제원을 출력하는 프로그램을 작성한 것이다.
result
manufacturer: 현대자동차
model: grandeur
color: black
maximum speed: 350
current speed: 0
changed speed: 60