Programming Language/Java

객체(Object)(1) - 객체 지향 언어, 클래스, 추상화, 캡슐화, 필드, 생성자, 메소드

Ma_Sand 2022. 2. 28. 23:04
반응형

1. 정의

 (1) 객체(Object)

     : 현존하는 모든 것들(유형, 무형, 사물, 개념 등)

       자신의 속성과 기능이 다른 것들과 구분되어 식별이 가능한 것들

       Java에서는 new 연산자를 통해 메모리 영역에 생성된 것을 말한다.      

new 연산자를 통해 메모리 영역에 생성된 배열도 객체에 해당한다.

 

 

 (2) 객체 지향 언어

     : '객체'를 지향하는 언어, '객체 중심'으로 운영된다.

 

 

 (3) 객체 지향 프로그래밍

     : 현존하는 모든 것들 간의 상호작용을 코드로 구현하는 과정

 

 

 

2. 클래스(class)

 (1) 정의

     : 구현하고자 하는 프로그램 상의 객체를 만들기 위해 객체들의 속성(특성)에 대해 정의한 것

 

 

 (2) 등장 배경

   ① "변수"로만 프로그래밍을 하면?

     ▷ 변수는 하나의 자료형에 하나의 값만 저장할 수 있다.

     ▷ '홍길동'과 '마이콜'이라는 객체를 만들어 보자. 그럼 이름과 나이, 성별이라는 속성이 필요하다. 

String name = "홍길동"; int age = 41; char gender = 'M';
String name = "마이콜"; int age = 25; char gender = 'M';

     ▷ 지금 당장 두 변수의 속성만 적었는데도 적어야할 것이 많다. 만약 직원 관리 프로그램을 만든다고 했을 때

         그 수많은 직원들이라는 변수를 언제 다 적고 있을 것인가? 만드는 건 둘째치고 관리하는 것도 힘들다.

         입사, 퇴사, 전보, 승진 등등.

 

   ② "배열"로만 프로그래밍을 하면?

     ▷ 배열은 하나의 자료형에 여러 개의 값을 저장할 수 있다.

     ▷ '직원'이라는 객체를 만들어 보자. 기본적인 속성을 생각해보면 이름과 나이, 성별 등이 있다.

String[] name = {"홍길동", "둘리", "마이콜", "도우너"};
int[] age = {41, 200, 25, 29};
char[] gender = {'M', 'M', 'M', 'F'};

     ▷ 지금까지는 변수만 사용했을 때보다 배열만 사용했을 때가 더 깔끔해보인다. 하지만 '둘리'가 퇴사를 한다면

         1번 인덱스에 있는 정보들을 전부 삭제해야 한다. 그렇지 않으면 데이터가 이상해진다. 왜냐? 배열에 입력되지

         않은 누군가가 입사를 한다면, 배열 내에서 인덱스 값이 앞당겨져서 '마이콜'이 200살 남자가 되고 '도우너'가

         25살 남자가 될 수 있다. 그리고 배열을 복사해서 배열의 크기를 더 늘려주어야 하는 번거로움이 생긴다.

 

   ③ 이러한 단점들을 보완하기 위해 나온 것이 "구조체"이다.

     ▷ 구조체는 여러 개의 자료형에 여러 개의 값을 저장할 수 있다.

     ▷ 문자열 String, 문자형 char, 정수형 int, 실수형 double 등 전부 저장할 수 있다.

 

   ☞ Java에서 클래스(class)는 "구조체 + 메소드(기능)"을 의미한다. 즉, 여러 개의 자료형과 메소드들을 모아서 만든

       틀이라고 생각하면 된다.

 

     **객체의 속성을 담아내는 틀을 VO(Value Object)라고 한다.

 

 

 (3) 특징

   ① 사물이나 개념의 구성요소를 추상화하여 정의한다.

   ② 캡슐화를 통해 기능을 포함한다.

 

 

 (4) 클래스를 만드는 과정

   ① 1단계: 추상화를 한다.

   ② 2단계: 캡슐화를 한다.

 

 

 

3. 추상화(abstraction)

 (1) 정의

     : 유연성을 확보하기 위해 구체적인 것은 제거하고 필요한 공통점을 추출하는 것

 

 

 (2) 추상화하는 과정

   ① 구현하려는 프로그램에서 필요한 객체들이 무엇인지 생각한다.

         ex) 직원 관리 프로그램은 '직원'이라는 객체가 필요하다.

   ② 그 객체들이 가진 공통적인 속성이나 기능들을 모두 추출한다.

         ex) 이름, 나이, 성별, 주민등록번호, 주소, 부서, 직급 등

   ③ 추출한 속성들을 구현하려는 프로그램의 기준에 맞추어 불필요한 속성들을 제거한다.

         ex) 자매형제, 시력 등

   ④ 최종적으로 추려진 속성들로 클래스를 만든다.

 

public static void main(String[] args) {

    // Employee 클래스 생성하기(Employee 클래스라는 틀에 '직원'이라는 객체를 생성)
    Employee person1 = new Employee();
    
    // Employee 클래스에 있는 속성에 직접적으로 값을 대입한다.
    // 속성: 이름, 나이, 성별
    person1.name = "홍길동";
    person1.age = 41;
    person1.gender = 'M';
    
    Employee person2 = new Employee();
    person2.name = "둘리";
    person2.age = 200;
    person2.gender = 'M';
    
    Employee person3 = new Employee();
    person3.name = "마이콜";
    person3.age = 25;
    person3.gender = 'M';
    
    // 위의 Employee 클래스 출력하기
    System.out.println(person1.name);
    System.out.println(person1.age);
    System.out.println(person1.gender);
    
    System.out.println(person2.name);
    System.out.println(person2.age);
    System.out.println(person2.gender);
    
    System.out.println(person3.name);
    System.out.println(person3.age);
    System.out.println(person3.gender);
}

▼실행결과

홍길동
41
M
둘리
200
M
마이콜
25
M

 

 

4. 캡슐화(encapsulation)

 (1) 정의

    : 추상화를 통해 정리된 구조체(데이터)와 메소드(기능)을 한데 묶어서 관리하는 것

 

 

 (2) 캡슐화를 하는 이유

    : 쉽게 말해서 데이터의 접근을 제한하기 위해서다. 접근제한자가 public일 때에는 여러 사람들이 해당 필드에

      접근할 수 있다. 그런데 모든 사람들이 보면 안되는 개인정보의 경우에는 접근제한자를 private로 하여 만든

      사람만 접근할 수 있게 해야한다. 이때 사용하는 기법이 캡슐화이다.(정보 은닉 효과)

   - 클래스 외부의 직접 접근을 방지하고 데이터를 처리하는 함수들을 클래스 내부에 작성한다.

 

     **접근제한자: 필드에 접근할 수 있는 범위를 제한한다.

         - public > protected > default > private (왼쪽에서 오른쪽으로 갈수록 제한 범위가 커진다.)

         - 클래스 안에서 필드를 선언할 때 반드시 접근제한자를 써야 한다.

         - public: 같은 패키지 내에서 접근 가능하고 전체에서 접근 가능하다.

           (default): 같은 패키지 내에서 접근 가능하다.

 

 

 (3) 캡슐화하는 과정

  ① 1단계: 값을 숨긴다.

    ⓐ 본인만 접근할 수 있도록 접근제한자를 public에서 private으로 변경한다.

 

  ② 2단계: 값에 간접 접근하는 메소드(기능)을 생성한다.

    ⓐ setter 메소드: 속성에 값을 대입해주는 메소드

    ⓑ getter 메소드: 속성에 저장된 값을 꺼내오는 메소드

    ⓒ 주의

      - 메소드에 작성해야 한다.

      - 모든 필드 변수에 만들어주어야 한다.

      - 명명규칙(낙타봉 표기법)을 지켜야 한다. ex) setName, getAge 등

 

 

 

5. 필드(Field)

 (1) 필드

    : 각 정보를 담는 부분

   - 필드 == 전역 변수 == 멤버 변수 == 인스턴스 변수

 

 

 (2) 표현법

접근제한자 예약어 class 클래스명 {

    접근제한자 예약어 자료형 변수명(=초기값);
    
}

 

//접근제한자 자료형 변수명;
private String name;
private int age;
private char gender;

 

   ① 예약어

     ⓐ static: 같은 타입의 여러 객체가 공유할 목적의 필드에서 사용하며, 프로그램 시작 시, 정적 메모리 영역에

                 자동 할당되는 멤버에 적용된다.(가장 먼저 실행된다.)

public class Company {
    private static int num1;
}

 

     ⓑ final: 하나의 값만 계속 저장해야 하는 변수에 사용한다.

public class Company {
    private final int age1 = 23;
    private int age3 = 39;
}

 

 

 

6. 생성자(constructor)

 (1) 역할

    : 객체가 new 연산자를 통해 heap 메모리 영역에 할당될 때 객체 안에서의 필드를 초기화한다.

      일종의 메소드이며, 초기값을 받아 객체의 필드에 기록한다.

 

 

 (2) 규칙

    : 생성자명을 클래스명과 똑같이 해야 한다. (public 생성자명)

 

 

 (3) 표현법

접근제한자 예약어 class 클래스명 {
    // 기본 생성자
    접근제한자 클래스명() {}
    
    // 매개변수 생성자
    접근제한자 클래스명(매개변수) {(this.)필드명 = 매개변수;}
}

 

public class Company {
    private int employeeNo;
    private String name;
    
    // 기본 생성자
    public Company() {} 
    
    // 매개변수 생성자
    public Company(int employeeNo, String name) {
        this.employeeNo = employeeNo;
        this.name = name;
    }
}

   ① 기본 생성자: 생성자를 작성하지 않은 경우에는 JVM이 자동으로 생성해놓는다. 왜냐하면 heap 메모리 영역에

                        객체를 생성해야 하는데 빈 공간이 있으면 안되니까 생성한다. 기본 생성자는 필드를 기본값으로

                        초기화하는 메소드라고 볼 수 있다.

 

   ② 매개변수 생성자: 객체를 생성할 때 전달받은 값으로 객체를 초기화하기 위해 사용한다. 매개변수 생성자는

                              JVM이 자동으로 생성하지 않는다. 오버로딩을 이용하여 작성한다.

 

      **오버로딩

        : 클래스 내에 동일한 이름의 메소드를 여러 작성하는 것이다.

        - 조건: 같은 메소드의 이름이어야 하고, 다른 매개변수의 개수 또는 다른 매개변수 타입이어야 한다.

 

 

 (4) this와 this()

   ① this란

     : 모든 인스턴스의 메소드에 숨겨진 채로 존재하는 레퍼런스이고, 할당된 객체를 가리킨다.

       함수를 실행했을 때 전달되는 객체의 주소를 자동으로 받는다.

public class Company {
    private String name;
    public Company() {}
    public Company(String name) {this.name = name;}
}

 → 위처럼 매개변수를 가진 생성자에서 매개변수명이 필드명과 같은 경우에는 필드명 앞에 this. 를 붙여 대입되는

     변수가 필드라는 것을 구분해준다.

 

   ② this()란

     : 같은 클래스의 다른 생성자를 호출할 때 사용하며, 반드시 첫 번째 줄에 선언해야 한다.

public class Company {
    private String name;
    private int age;
    public Company() {this("마이콜", 25);}
    public Company(String name, int age) {
        this.name = name; 
        this.age = age;
    }
}

 

 

 

7. 메소드(method)

 (1) 메소드란

    : 전달값이 없는 상태로 호출하거나 어떤 값을 전달하기 위해 호출하며, 함수 내에 작성된 연산을 수행한다.

      수행한 후에 반환값이나 결과값이 있을 수도, 없을 수도 있다.

 

 

 (2) 표현법

접근제한자 예약어 반환형 메소드명(매개변수) {
    수행하려는 코드
}

public void info() {
    System.out.println(employeeNo);
}

 

 

 (3) 접근제한자

구분 클래스 패키지 자손 클래스 전체
(+) public O O O O
(#) protected O O O  
(~) (default) O O    
(-) private O      

protected는 상속 관계

 

 

(4) 예약어

구분 전체
static static 영역에 할당하여 객체의 생성 없이 사용한다.
final 상속 시에 오버라이딩이 불가능하다.
abstract 상속해서 오버라이딩으로 완성시켜 사용해야 한다.
synchronized 동기화 처리. 공유 자원에 하나의 스레드만 접근할 수 있다.
static final
(final static)
static과 final의 의미를 둘 다 가진다.

 

 

 (5) 반환형

구분 전체
void 반환형이 없다는 것을 의미한다. 반환값이 없을 때 반드시 작성해야 한다.
기본 자료형 연산을 수행한 후 반환값이 기본 자료형일 경우에 사용한다.
배열 연산을 수행한 후 반환값이 배열인 경우에 배열의 주소값이 반환된다.
클래스 연산을 수행한 후 반환값이 해당 클래스 타입의 객체일 경우에 해당 객체의 주소값이 반환된다.

 

 

 (6) 매개변수

구분 전체
() 매개변수가 없는 것을 의미한다.
기본 자료형 기본형 매개변수 사용 시 값을 복사하여 전달한다.
매개변수값을 변경해도 원래 값은 변경되지 않는다.
배열 배열, 클래스 등 참조형을 매개변수로 전달할 때는 데이터의 주소값을 전달하기 때문에 매개변수를 수정하면 원래의 데이터가 수정된다.(얕은 복사)
클래스 "
가변인자 매개변수의 개수를 유동적으로 설정하는 방법이다.
가변 매개변수 외에 다른 매개변수가 있으면 가변 매개변수를 마지막에 설정한다. (자료형 ... 변수명)

 ** 매개변수는 그 수의 제한이 없다.

 

 

 (7) 표현법

   ① 매개변수가 없고 return값은 있을 때

접근제한자 예약어 반환형 메소드명() {
    실행하려는 코드
}

public int info() {
    return employeeNo;
}

 

   ② 매개변수가 없고 return값도 없을 때

접근제한자 예약어 void 메소드명() {
    실행하려는 코드
}

public void info() {
    System.out.println(employeeNo);
}

 

   ③ 매개변수도 있고 return값도 있을 때

접근제한자 예약어 반환형 메소드명(자료형 변수명) {
    실행하려는 코드
}

public String info(String employeeName) {
    return employeeName + " " + employeeName;
}

 

   ④ 매개변수가 있고 return값이 없을 때

접근제한자 예약어 void 메소드명(자료형 변수명) {
    실행하려는 코드
}

public void info(String employeeName) {
    System.out.println(employeeNo + " " + employeeName);
}

 

 

 

 (8) setter 메소드와 getter 메소드

   ① setter 메소드

     : 필드에 값을 대입하는 메소드

접근제한자 예약어 void set필드명(자료형 변수명) {
    (this.)필드명 = 자료형 변수명;
}

public void setName(String name) {
    this.name = name;
}

 

   ② getter 메소드

     : 필드에 기록된 값을 읽어서 가져오는 메소드

접근제한자 예약어 반환형 get필드명() {
    return 필드명;
}

public String getName() {
    return name;
}
반응형