본문 바로가기

JAVA/이것이 자바다

Chapter .06-1 클래스

6.1 객체 지향 프로그래밍

- OOP: Object Oriented Programming

- 부품 객체를 먼저 만들고 이것들을 하나씩 조립해 완성된 프로그램을 만드는 기법

 

현실 세계에서 어떤 제품을 만들 때, 부품을 먼저 개발하고 이 부품들을 하나씩 조립해서 완성된 제품을 만들듯이, 소프트웨어를 개발 할 때도 부품에 해당하는 개체들을 먼저 만들고, 이것들을 하나씩 조립해서 완성된 프로그램을 만든다.이러한 기법을 객체지향 프로그래밍(OOP : Object Oriented Programming)이라고 한다.

 

6.1.1 객체란?

객체(Object)란 물리적으로 존재하거나 추상적으로 생각할수 있는 것 중에서 자신의 속성을 가지고 있고 다른 것과 식별 가능한 것을 말한다.

 

- 물리적으로 존재하는 것 (자동차, 책, 사람)

- 추상적인 것(회사, 날짜) 중에서 자신의 속성과 동작을 가지는 모든 것

- 객체는 필드(속성) 과 메소드(동작)로 구성된 자바 객체로 모델링 가능

 

자바에서 속성 : 필드, 동작 : 메소드 라고 부른다.

현실 세계의 객체를 소프트웨어 객체로 설계하는 것을 객체 모델링(Object Medeling) 이라고 한다.

 

 

6.1.2 객체의 상호작용

- 객체들은 서로 간에 기능(동작)을 이용하고 데이터를 주고 받음

 

현실 세계에서 일어나는 모든 현상은 객체와 객체 간의 상호작용으로 이루어져 있다.

예를 들어 사람은 전자계산기의 기능을 이용하고, 전자계산기는 계산 결과를 사람에게 알려주는 상호작용을 한다.

 

소프트웨어에서도 마찬가지이다. 객체들은 각각 독립적으로 존재하고, 다른 객체와 서로 상호작용하면서 동작한다.

객체들 사이의 상호작용 수단은 메소드이다.

객체가 다른 객체의 기능을 이용하는 것이 바로 메소드 호출이다.

메소드 호출은 다음과 같은 형태를 가지고 있다.

객체에 도트( . ) 연산자를 붙이고 메소드 이름을 기술하면 된다.

도트 연산자는 객체의 필드와 메소드에 접근할때 사용한다.

리턴값 = 전자계산기객체.메소드(매개값1, 매개값2, ....);

 

6.1.3 객체 간의 관계

- 객체 지향 프로그램에서는 객체는 다른 객체와 관계를 맺음

- 관계의 종류

   • 집합 관계: 완성품과 부품의 관계

   • 사용 관계: 객체가 다른 객체를 사용하는 관계

   • 상속 관계: 종류 객체와  구체적인 사물 객체 관계

 

객체는 개별적으로 사용될 수 있지만, 대부분 다른 객체와 관계를 맺고 있다.

이 관계의 종류에는 집합 관계, 사용 관계, 상속 관계가 있다.

 

사용관계는 객체 간의 상호작용을 말한다.

객체는 다른 객체의 메소드를 호출하여 원하는 결과를 얻어낸다.

예를 들어 사람은 자동차를 사용하므로 사람과 자동차는 사용관계라고 볼 수 있다.

 

상속관계는 상위(부모) 객체를 기반으로 하위(자식) 객체를 생성하는 관계를 말한다.

일반적으로 상위 객체는 종류를 의미하고, 하위 객체는 구체적인 사물에 해당한다.

예를들어 "자동차는 기계의 종류이다." 에서 기계(상위)와 자동차(하위)는 상속관계에 있다고 볼 수 있다.

 

 

6.1.4 객체 지향 프로그래밍의 특징

객체 지향 프로그램의 특징으로는 캡술화, 상속, 다형성을 들 수 있다.

 

캡슐화

   • 객체의 필드, 메소드를 하나로 묶고, 실제 구현 내용을 감추는 것

   • 외부 객체는 객체 내부 구조를 알지 못하며 객체가 노출해 제공하는 필드와 메소드만 이용 가능

   • 필드와 메소드를 캡슐화하여 보호하는 이유는 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록

   • 자바 언어는 캡슐화된 멤버를 노출시킬 것인지 숨길 것인지 결정하기 위해 접근 제한자(Access Modifier) 사용

 

 

상속

   • 상위(부모) 객체의 필드와 메소드를 하위(자식) 객체에게 물려주는 행위

   • 하위 객체는 상위 객체를 확장해서 추가적인 필드와 메소드를 가질 수 있음

   • 상속 대상: 필드와 메소드

   • 상속의 효과

      – 상위 객체를 재사용해서 하위 객체를 빨리 개발 가능

      – 반복된 코드의 중복을 줄임

      – 유지 보수의 편리성 제공

      – 객체의 다형성 구현

 

 

다형성 (Polymorphism)

  • 같은 타입이지만 실행 결과가 다양한 객체를 대입할 수 있는 성질

      – 부모 타입에는 모든 자식 객체가 대입

      – 인터페이스 타입에는 모든 구현 객체가 대입

  • 효과

      – 객체를 부품화시키는 것 가능

      – 유지보수 용이

 

 

 

6.2 객체와 클래스

- 객체(Object)와 클래스(Class)

    현실세계:  설계도 → 객체

     자바:       클래스  객체

     클래스에는 객체를 생성하기 위한 필드와 메소드가 정의

     클래스로부터 만들어진 객체를 해당 클래스의 인스턴스(instance)

    하나의 클래스로부터 여러 개의 인스턴스를 만들 수 있음

 

현실에서 객체는 갑자기 하늘에서 떨어지는 것이 아니라, 설계도를 바탕으로 만들어진다.

예를 들어 사람들이 자동차를 이용하기 위해서는 우선 공장에서 설계도를 보고 자동차를 만들어야 한다.

객체 지향 프로그래밍에서도 마찬가지다.

메모리에서 사용하고 싶은 객체가 있다면 우선 설계도로 해당 객체를 만드는 작업이 필요하다.

 

자바에서는 설계도가 바로 클래스(class)이다.

클래스에는 객체를 생성하기 위한 필드와 메소드가 정의되어 있다.

 

클래스로 부터 만들어진 객체를 인스턴스(instance)라고 한다.

자동차 객체는 자동차 클래스의 인스턴스인 셈이다.

 

그리고 클래스로 부터 객체를 만드는 과정을 인스턴스화라고 한다.

하나의 클래스로 부터 여러개의인스턴스를 만들 수 있는데, 이ㅣ것은 동일한 설계도로부터 여러 대의 자동차는 만드는 것과 동일하다.

 

 

객체지향 프로그래밍 개발은 세 가지 단계가 있다.

1. 클래스를 설계해야 한다.

2. 설계된 클래스로 사용할 객체를 생성해야 한다.

3. 생성된 객체를 이용한다.

 

 

6.3 클래스 선언

클래스 이름 생성 규칙

   - 한글 이름도 가능하나, 영어 이름으로 작성

   - 알파벳 대소문자는 서로 다른 문자로 인식

   - 첫 글자와 연결된 다른 단어의 첫 글자는 대문자로 작성하는 것이 관례

public class 클래스이름{

}

public class Car{

}

여기에서 public class 키워드는 반드시 소문자로 작성해야 한다.

클래스 이름 뒤에는 반드시 중괄호 { } 를 붙여주는데, 중괄호 시작 { 은 클래스의 시작을 , } 끝을 알려준다.

 

일반적으로 클래스는 소프 파일당 하나를 생성한다.

하지만 여러개도 생성이 가능하다.

public class Car{

}

class Tire{

}

두 개 이상의 클래스가 선언된 소스 파일을 컴파일 하면 바이트 코드 파일은(.class) 클래스를 선언 한 개수만큼 생긴다.위 파일을 컴파일 하면 Car.class, Tire.class가 각각 생성된다.

주의할 점은 소스파일과 동일한 이름의 클래스에만 접근제한자(public)을 붙일 수 있다.

 

 

6.4 객체 생성과 클래스 변수

- new 연산자(객체 생성 역할)

   • 클래스( )는 생성자를 호출하는 코드

   • 생성된 객체는 힙 메모리 영역에 생성

- new 연산자는 객체를 생성 후, 객체 생성 번지 리턴

 

클래스를 선언한 다음, 컴파일을 해싿면 객체를 생성할 설계도가 만들어진 셈이다.클래스로 부터 객체를 생성하는 방법은 다음과 같이 new 연산자를 사용하면 된다.

객체 생성

- 클래스 변수

   • new 연산자에 의해 리턴 된 객체의 번지 저장 (참조 타입 변수)

   • 영역의 객체를 사용하기 위해 사용

 

이렇게 new 연산자로 객체를 생성하고 리턴된 객체의 주소를 변수에 저장하면 변수가 객체를 참조하게 된다.

public class Student{
}
public class StudentExample{
	public static void main(String[] args){
		Student s1 = new Student();
        Student s2 = new Student();
    }
}

위 코드가 실행되면 메모리에 클래스 변수와 객체가 생성된다.

Student 클래스는 하나지만 new 연산자를 사용한 만큼 객체가 메모리에 생성된다.

이러한 객체들은 Student클래스의 인스턴스들이다.

 

비록 같은 클래스로 부터 생성 되었지만, 각각의 Student 객체는 자신만의 고유 데이터를 가지면서 메모리에서 활동하게 된다.S1과 S2가 참조하는 Student 객체는 완전히 독립된 서로 다른 객체이다.

 

 

6.5 클래스의 구성 멤버

클래스에는 객체가 가져야 할 구성 멤버가 선언된다.

 

- 클래스의 구성 멤버

   • 필드(Field)

   • 생성자(Constructor)

   • 메소드(Method)

 

 

6.6 필드

필드는 객체의 고유 데이터, 객체가 가져야 할 부품, 객체의 현재 상태 데이터를 저장하는 곳이다.

 

자동차 객체로 예를 들면 제작회사, 모델, 색깔, 최고속도는 고유데이터에 해당하고,

현재 속도, 엔진회전수는 상태 데이터에 해당한다.

차체, 엔진, 타이어는 부품에 해당한다.

 

따라서 자동차 클래스를 선언할 때 이 정보들은 필드로 선언되어야 한다.

 

 

6.6.1 필드 선언

필드 선언은 클래스 중괄호 { } 블록 어디서든 존재할 수 있다.

생성자 선언과 메소드 선언의 앞과 뒤 어떤 곳에서도 필드 선언이 가능한다.

 

하지만 메소드 중괄호 블록 내부에는 선언될 수 었다.

 

타입필드 [= 초기값];

String company = "현대자동차";
String model = "그랜저";
int maxSpeed = 300;
int productionYear;
int currentSpeed;
boolean enineStart;

초기화 되지 않은 필드는 기본값으로 설정된다.

 

6.6.2 필드 사용

- 필드 사용

  필드 값을 읽고, 변경하는 작업을 말한다.

- 필드 사용 위치

   • 객체 내부: “필드이름으로 바로 접근

    객체 외부: “변수.필드이름으로 접근

6.7 생성자(Constructor)

생성자(Constructor)는 new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 떄 호출이 되는 객체의 초기활르 담당한다.

객체 초기화란 필드를 초기화하거나, 메소드를 호출해서 객체를 사용할 준비를 하는 것을 말한다.

생성자를 실행시키지 않고는 클래스로부터 객체를 만들 수 없다.

 

new 연산자에 의해 생성자가 성공적으로 실행되면 힙(heap) 영역에 객체가 생성되고 객체의 주소가 리턴된다.

 

6.7.1 기본 생성자

모든 클래스는 생성자가 반드시 존재하며 하나 이상을 가질 수 있다.

 

우리가 클래스 내부에 생성자 선언을 생략 했다면 컴파일러는 기본생성자(default Constructor)를 바이트 코드에 자동으로 추가 시킨다.

 

 

 

6.7.2. 생성자 선언

기본 생성자 대신 우리가 생성자를 명시적으로 선언하려면 다음과 같은 형태로 작성하면 된다.

public class Car{
	Car(String model, String color, int maxSpeed){
    
    }
}
Car myCar = new Car("그랜저", "검정", 300);

 

 

6.7.3 필드 초기화

- 초기값 없이 선언된 필드는 객체가 생성될 때 기본값으로 자동 설정

 

- 다른 값으로 필드 초기화하는 방법

   • 필드 선언할 때 초기값 설정

   • 생성자의 매개값으로 초기값 설정

   

Korean k1 = new Korean("박자바","011154-1234567");
Korean k1 = new Korean("김자바","022222-1234567");

   • 매개 변수와 필드명 같은 경우 this 사용 (p.206~208)

public Korean(String name, String ssn){
	this.name = name;
    this.ssn = ssn;
}

 

 

6.7.4 생성자 오버로딩(Overloading)

 - 매개변수의 타입, 개수, 순서가 다른 생성자 여러 개 선언

public class Car{
	Car(){....}
    
    Car(String model){ .....}
    
    Car(String model, String color){.....}
    
    Car(String model, String color, int maxSpeed){.....}

}

 

아래와 같이 순서만 바꾸었다면 생성자 오버로딩이라고 볼 수 없다.

Car(String model, String color){.....}
Car(String color, String model){.....}

 

생성자가 오버로딩 되어 있을 경우, new 연산자로 생성자를호출할 때 제공되는 매개값의 타입과 수에 의해 호출될 생성자가 결정된다.

Car car1 = new Car();
Car car2 = new Car("그랜저");
Car car3 = new Car("그랜저","흰색");
Car car4 = new Car("그랜저","흰색",300);

 

 

 

6.7.5 다른 생성자 호출(this())

생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있다.

매개 변수의 수만 달리하고 필드 초기화 내용이 빗스한 생성자에서 이러한 현상을 많이 볼 수 있다.

이 경우에는 필드 초기화 내용은 한 생성자에만 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있다.

 

중복코드가 많은 생성자

car(String model){
	this(model,"은색",250);
}

Car(String model, String color){
	this(model,color,250);
}

//이 생성자가 호출 된다.
Car(String model, String color, int maxSpeed){
	this.model = model;
    this.color = color;
    this.maxSpeed = maxSpeed;
}

 

 

6.8 메소드

메소드는 객체의 동작에 해당하는 중괄호 { } 블록을 말한다.

 

- 객체의 동작(기능)

- 호출해서 실행할 수 있는 중괄호 { } 블록

- 메소드 호출하면 중괄호 { } 블록에 있는 모든 코드들이 일괄 실행

 

6.8.1 메소드 선언

 

 

메소드 리턴 타입

 - 메소드 실행된 후 리턴하는 값의 타입

 - 메소드는 리턴값이 있을 수도 있고 없을 수도 있음

//메소드 선언
void powerOn(){......}
double divide(int x , int y){
     return x / y;
}


//메소드 호출
poserOn();
double result = divide(1,2);

 

메소드 이름

 - 숫자로 시작하면 안되고, $와 _를 제외한 특수문자를 사용하지 말아야 한다.

 - 관례적으로 메소드명은 소문자로 작성한다.

 - 서로 다른 단어가 혼합된 이름이라면 뒤이어 오는 단어의 첫머리 글자는 대문자로 작성한다.

void run(){....}
void startEngine(){....}
String getname(){....}
int[] getScores(){....}

 

매개 변수 선언

 - 매개변수는 메소드를 실행할 때 필요한 데이터를 외부에서 받기 위해 사용

 - 매개변수도 필요 없을 수 있음

 

매개 변수의 수를 모를 경우

매개 변수는 이미 정해져 있는 것이 일반적이지만, 경우에 따라선느 메소드를 선언할 떄 매개 변수의 개수를 알 수 없는 경우가 있다.

매개 변수를 배열 타입으로 선언하여 해결 할 수 있다.

int sum1(int[] values){
	int sum = 0;
    for(int i=0;i<values.length;i++){
    	sum += values[i];
	}
    return sum;
}

 

 

6.8.2 리턴(return)문

리턴값이 있는 메소드

메소드 선언에 리턴 타입이 있는 메소드는 반드시 리턴(return)문을 사용해서 리턴값을 지정해야 한다.

리턴값이 없는 메소드(void)

void 로 선언된 리턴값이 없는 메소드에서도 return문을 사용 할 수 있다.

return을 사용하면 메소드를 강제 종료 할 수 있다.

 

6.8.3 메소드 호출

- 메소드는 클래스 내∙외부의 호출에 의해 실행

  • 클래스 내부: 메소드 이름으로 호출 (p.225~228)

  • 클래스 외부: 객체 생성 후, 참조 변수를 이용해 호출 (p.228~229)

 

 

 

6.8.4 메소드 오버로딩

클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것을 메소드 오버로딩(overloading)이라고 한다.

class Calculator{

	int plus(int x, int y){
    	return x + y;
	}
	
    doubld plus(double x, double y){
    	return x + y;
    }
}

 

'JAVA > 이것이 자바다' 카테고리의 다른 글

Chapter .07 상속  (0) 2021.07.17
Chapter .06-2 클래스  (0) 2021.07.16
Chapter .05 참조 타입  (0) 2021.07.06
Chapter .04 조건문과 반복문  (0) 2021.07.05
Chapter .03 연산자  (0) 2021.07.02