콘텐츠로 이동

클래스와 객체 (1)

1. 객체지향과 자바

1) 세상 모든 것이 객체다

실 세계 객체의 특징

  • 객체마다 고유한 특성(state)와 행동(behavior)를 가짐
  • 다른 객체들과 정보를 주고 받는 등, 상호작용하면서 살아감

컴퓨터 프로그램에서 객체 사례

  • 테트리스 게임의 각 블록들
  • 한글 프로그램의 메뉴나 버튼들

2) 자바의 객체 지향 특성 : 캡슐화

캡슐화 : 객체를 캡슐로 싸서 내부를 볼 수 없게 하는 것

  • 객체의 가장 본질적인 특징
  • 외부의 접근으로부터 객체 보호

자바의 캡슐화

  • 클래스(class): 객체 모양을 선언한 틀(캡슐화하는 틀)
  • 객체: 생성된 실체(instance)
  • 클래스 내에 메소드와 필드 구현

3) 자바의 객체 지향 특성 : 상속

  • 상위 개체의 속성이 하위 개체에 물려짐
  • 하위 개체가 상위 개체의 속성을 모두 가지는 관계

실 세계의 상속 사례

graph BT
  A[어류] --> B[동물];
  C[사람] -->B;

  D[나무] --> E[식물];
  F[풀] -->E;
  B-->G[생몰];
  E-->G;

나무는 식물의 속성과 생물의 속성을 모두 가짐
사람은 생물의 속성은 가지지만 식물의 속성은 가지고 있지 않음

  • 상위 클래스의 멤버를 하위 클래스가 물려받음
  • 상위 클래스 : 슈퍼 클래스
  • 하위클래스 : 서브클래스, 슈퍼클래스코드의 재사용, 새로운 특성 추가가능
class Animal {
  String  name;
  int age;
  void eat {...};
  void speak {...};
  void love {...};
}

// 상속
class Human extends Animals {
  String hobby;
  String job;

  void work {...};
  void cry {...};
  void laugh {...};

}

4) 자바의 객체 지향 특성 : 다형성

같은 이름의 메소드가 클래스 혹은 객체에 따라 다르게 구현되는 것

  • 메소드 오버로딩 : 한 클래스 내에서 같은 이름이지만 다르게 작동하는 여러 메소드
  • 메소드 오버라이딩 : 슈퍼 클래스의 메소드를 동일한 이름으로 서브 클래스마다 다르게 구현

5) 객체 지향 언어의 목적

소프트웨어의 생산성 향상

  • 컴퓨터 산업 발전에 따라 소프트웨어의 생명 주기(life cycle) 단축: 소프트웨어를 빠른 속도로 생산할 필요성 증대
  • 객체지향언어: 상속, 다형성, 객체, 캡슐화등 소프트웨어 재사용을 위한 여러 장치 내장, 소프트웨어 재사용과 부분 수정 빠름, 소프트웨 어를 다시 만드는 부담 대폭 줄임, 소프트웨어 생산성 향상

실 세계에 대한 쉬운 모델링

  • 초기프로그래밍:수학계산/통계처리를하는등처리과정,계산 절차 중요
  • 현대 프로그래밍 : 컴퓨터가 산업 전반에 활용, 실 세계에서 발생하는 일을 프로그래밍, 실 세계에서는 절차나 과정보다 물체(객체)들의 상호 작용으로 묘사하는 것이 용이
  • 객체지향언어: 실세계의 일을 보다 쉽게 프로그래밍하기위한 객체 중심적 언어

6) 절차 지향 프로그래밍과 객체 지향 프로그래밍

절차 지향 프로그래밍

  • 작업 순서를 표현하는 컴퓨터 명령 집합
  • 함수들의 집합으로 프로그램 작성

객체 지향 프로그래밍

  • 컴퓨터가 수행하는 작업을 객체들간의 상호 작용으로 표현
  • 클래스 혹은 객체들의 집합으로 프로그램 작성

절차지향적 프로그래밍의 실행 절차


graph LR
  A([시작]) --> B[동전입력]
  B--> C{돈이 충분 한가?}
  C--> |아니오| B 
  C--> |예| D[상품선택]
  D-->E{상품 재고 있나요?}
  E--> |아니오| D
  E--> |예| F[상품인도]

객체지향적 프로그래밍의 객체들의 상호 관련성


graph BT

b[버튼1]
c[버튼2]
d[버튼3]
a[디스플레이]

b-->e[자판기 엔진]
c-->e
d-->e
e-->a

direction BT

e---->f[돈통통]
e---->g[커피통]
e---->h[물통]
e---->i[프림통]
e---->j[컵통]

7) 클래스와 객체

클래스

  • 객체의 속성(state)과 행위(behavior) 선언
  • 객체의설계도혹은틀

객체

  • 클래스의 틀로 찍어낸 실체
  • 프로그램 실행 중에 생성되는 실체
  • 메모리 공간을 갖는 구체적인 실체
  • 인스턴스(instance)라고도 부름

사례

클래스 객체
소나타자동차 출고된 실제 소나타 100대
벽시계 우리집벽에걸린벽시계들
책상 우리가 사용중인 실제 책상들

붕어빵 틀은 클래스이며, 이 틀의 형태로 구워진 붕어빵은 바로 객체입니다.
붕어빵은 틀의 모양대로 만들어지지만 서로 조금씩 다릅니다.

  • 치즈 붕어빵, 크림 붕어빵, 앙꼬 붕어빵 등이 있습니다. 그래도 이들은 모두 붕어빵입니다.

객체들은 클래스에 선언된 동일한 속성을 가지지만 속성 값은 서로 다름

2. 자바 클래스, 생성자

1) 자바 클래스의 구성

  • class 키워드로 선언
  • 멤버 : 클래스 구성 요소
  • 필드(멤버 변수)와 메소드(멤버 함수)
  • 클래스에 대한 public 접근 지정 : 다른 모든 클래스에서 클래스 사용 허락
  • 멤버에 대한 public 접근 지정 : 다른 모든 클래스에게 멤버 접근 허용
  public class Circle {
    // 변수
    int radius;
    String name;

    public double getArray() { // 메소드
      return 3.14 * radius * radius;
    }
  }

2) Circle 클래스의 객체 생성 및 활용

[예제 4-1]
  public class Circle {
    int radius; // 원의 반지름을 저장하는 멤버 변수 
    String name; // 원의 이름을 저장하는 멤버 변수

    public double getArea() { // 멤버 메소드 
      return 3.14 * radius * radius;
    }

    public static void main(String[] args) {
      Circle pizza;
      pizza = new Circle();
      pizza.radius = 10;
      pizza.name = "자바피자";
      double area = pizza.getArea(); 
      System.out.println(pizza.name + "의 면적은 " + area);

      Circle donut = new Circle();
      donut.radius = 2;
      donut.name = "자바도넛";
      area = donut.getArea(); 
      System.out.println(donut.name + "의 면적은 " + area);
    }
  }

자바피자의 면적은 314.0
자바도넛의 면적은 12.56

3) Rectangle 클래스 만들기 연습

[예제 4-2] 너비(width)와 높이(height) 필드, 그리고 면적 값을 제공하는 getArea() 메소드를 가진 Rectangle 클래스를 작성하라.
public class Rectangle {
  int width;
  int height;
  int getArea() {
    return width * height; 
  }

  public static void main(String[] args) {
    Rectangle rect = new Rectangle(); // 객체 생성 
    rect.width = 4;
    rect.height = 5;
    System.out.println("사각형의 면적은 " + rect.getArea());
  } 
}

사각형의 면적은 20

4) 생성자

  • 객체가 생성될 때 초기화 목적으로 실행되는 메소드
  • 객체가 생성되는 순간에 자동 호출

5) 두 개의 생성자를 가진 Circle 클래스

[예제 4-3]
  public class Circle {
    int radius; 
    String name;

    public Circle() { // 매개 변수 없는 생성자 
      radius = 1; 
      name = ""; // radius의 초기값은 1
    }

    public Circle(int r, String n) { // 매개 변수를 가진 생성자 
      radius = r; 
      name = n;
    }

    public double getArea() {
      return 3.14 * radius * radius; 
    }

    public static void main(String[] args) {
      Circle pizza = new Circle(10, "자바피자"); // Circle 객체 생성, 반지름 10 
      double area = pizza.getArea();
      System.out.println(pizza.name + "의 면적은 " + area);

      Circle donut = new Circle(); // Circle 객체 생성, 반지름 1 
      donut.name = "도넛피자";
      area = donut.getArea(); 
      System.out.println(donut.name + "의 면적은 " + area);
    } 
  }

자바피자의 면적은 314.0 도넛피자의 면적은 3.14

6) 생성자의 특징

  • 생성자 이름은 클래스 이름과 동일
  • 생성자는 여러 개 작성 가능(생성자 중복)
      public class Circle {
        public Circle() {...} // 매개 변수 없는 생성자
        public Circle(int r, String n) {...} // 2개의 매개 변수를 가진 생성자
      }
    
  • 생성자는 객체 생성시 한 번만 호출 : 자바에서 객체 생성은 반드시 new 연산자로 함

      Circle pizza = new Circle(10, "자바피자"); // 생성자 Circle(int r, String n) 호출 
      Circle donut = new Circle(); // 생성자 Circle() 호출
    

  • 생성자의 목적은 객체 생성 시 초기화

  • 생성자는 리턴 타입을 지정할 수 없음
      public void Circle() {...} // 오류. void도 사용 안 됨
    

7) 생성자 선언 및 호출 연습

[예제 4-4] title과 author 필드를 가진 Book 클래스를 선언하고,필드 값을 매개변수로 받아 초기화하는 2개의 생성자를 작성하라.
  public class Book {
    String title;
    String author;

    public Book(String t) { // 생성자
      title = t;
      author = "작자미상"; }

    public Book(String t, String a) { // 생성자 
      title = t;
      author = a;
    }
    public static void main(String [] args) {
      Book javaBook = new Book("Java", "황기태"); // 2개의 매개변수 생성자 호출 
      Book bible = new Book("Bible"); // 1개의 매개변수 생성자 호출
    }
  }

8) 기본 생성자

  • 매개 변수 없고, 아무 작업 없이 단순 리턴하는 생성자
      class Circle {
        public Circle() { } // 기본 생성자
      }
    
  • 디폴트 생성자라고도 불림

9) 기본 생성자가 자동 생성되는 경우

  • 클래스에 생성자가 하나도 선언되어 있지 않을 때
  • 컴파일러에 의해 기본 생성자 자동 생성
public class Circle {
  int radius;
  void set(int r) { ridius = r; }
  double getArea() { return 3.14 * radius * radius; }

  public static void main(String[] args) {
    Circle pizza = new Circle(); // 호출 ->  컴파일러에 의해 자동 생성자 삽입  public Circle() {}
    pizza.set(5);
    System.out println(pizza.getArea());    
  }
}

10) 기본 생성자가 자동 생성되지 않는 경우

  • 클래스에 생성자가 선언되어 있는 경우
  • 컴파일러는 기본 생성자를 자동 생성해 주지 않는다.
  public class Circle {
    int radius;
    void set(int r) { radius = r; }
    double getArea() { return 3.14 * radius * radius; }

    public Circle(int r) {
      radius = r;
    }

    public static void main(string[] args) {
      Circle pizza  = new Circle(10);
      System.out.println(pizza.getArea());

      Circle donut = new Circle(); // 컴파일 오류 : 해당하는 생성자 없음
      System.out.println(donut.getArea());
    }
  }

3. this 레퍼런스, 객체 배열

1) this 레퍼런스

  • 객체 자신에 대한 레퍼런스
  • 컴파일러에 의해 자동 관리, 개발자는 사용하기만 하면 됨
  • this.멤버 형태로 멤버를 접근할 때 사용
  public class Circle { 

    int radius;

    public Circle() { 
      radius = 1; 
    } 
    public Circle(int r) { 
      radius = r; 
    } 
    double getArea() {
      return 3.14 * radius * radius; 
    }
    ...
  }
this를 사용하여 수정한 경우
  public class Circle { 

    int radius;

    public Circle() { 
      this.radius = 1; 
    }   
    public Circle(int radius) {
      this.radius = radius; 
    }
    double getArea() {
      return 3.14 * this.radius * this.radius;
    }
    ...
  }

2) 객체 속에서의 this

생략

3) this()로 다른 생성자 호출

  • 같은 클래스의 다른 생성자 호출
  • 생성자 내에서만 사용 가능
  • 생성자 코드의 제일 처음에 있어야 함
this() 사용 실패 사례
  public Book() {
    System.out.println("생성자 호출됨");
    this("", "", 0); // 생성자의 첫 번째 문장이 아니기 때문에 컴파일 오류
  }
[예제 4-5] this()로 다른 생성자 호출
  public class Book {
    String title;
    String author;
    void show() { 
      System.out.println(title + " " + author); 
    }
    public Book() {
      this("", "");
      System.out.println("생성자 호출됨"); 
    }
    public Book(String title) {
      this(title, "작자미상"); // public Book(String title, String author) 생성자 호출
    }    
    public Book(String title, String author) {
      this.title = title; 
      this.author = author; 
    }
    public static void main(String [] args) {
      Book javaBook = new Book("Java", "황기태"); 
      Book bible = new Book("Bible");
      Book emptyBook = new Book();
      bible.show(); 
    }
}

4) 객체 배열

객체에 대한 레퍼런스 배열임


자바의 객체 배열 만들기 3단계

  1. 배열레퍼런스 변수선언
  2. 레퍼런스 배열 생성
  3. 배열의 각 원소 객체생성
Circle [] c;                         // 1단계 : Circle 배열에 대한 레퍼런스 변수 c 선언
c = new Circle[5];                   // 2단계 : 레퍼런스 배열 생성

for (int i = 0; i < c.length; i++) 
  c[i] = new Circle(i);             // 3단계: 각 원소 객체 생성

for (int i = 0; i < c.length; i++)  // 모든 객체의 면적 출력
  System.out.pirnt((int)(c[i].getArea())+ " ")

5) 객체 배열 선언과 생성 과정

생략 (4 설명과 유사)

6) Circle 배열 만들기

[예제 4-6]
  class Circle {
    int radius;
    public Circle(int radius) {
      this.radius = radius; 
    }
    public double getArea() { 
      return 3.14 * radius * radius;
    } 
  }  
  public class CircleArray {
    public static void main(String[] args) {
      Circle [] c;
      c = new Circle[5];
      for(int i = 0; i < c.length; i++)
        c[i] = new Circle(i);
      for(int i = 0; i < c.length; i++) 
        System.out.print((int)(c[i].getArea()) + " ");
    } 
  }

7) 객체 배열 만들기

[예제 4-7] 예제 4-4의 Book 클래스를 활용하여 2개 Book 객체 배열을 만들고, 사용자 로부터 책의 제목과 저자를 입력 받아 배열을 완성하라
  import java.util.Scanner;

  class Book {
    String title, author;
    public Book(String title, String author) {
      this.title = title;
      this.author = author; 
    }
  }

 public class BookArray {
   public static void main(String[] args) {
     Scanner scanner = new Scanner(System.in);
     Book [] book = new Book[2]; // Book 배열 선언
     for(int i=0; i<book.length; i++) { 
       System.out.print("제목>>");
       String title = scanner.nextLine(); 
       System.out.print("저자>>");
       String author = scanner.nextLine();
       book[i] = new Book(title, author); // 배열 원소 객체 생성
     }
     for(int i=0; i<book.length; i++)
       System.out.print("(" + book[i].title + ", " + book[i].author + ")");
   } 
 }