우리는 이전 파트에서 자바의 기본 문법에 대해 알아보았다.
이번 파트에서는 데이터와 처리를 하나로 묶는 법! 객체지향 프로그래밍을 학습해보자.
객체 지향 프로그래밍
클래스와 객체
클래스 설계 및 구현
Object-Oriented Programming
definition >> 객체지향 프로그래밍(Object-Oriented Programming)이란, 조립식 프로그래밍이다. 객체를 조립하여 전체 프로그램을 만드는 것이다.
plus >> 조립식으로 프로그램을 만들면 좋다. 고장이 나도 해당 부분만 수리하면 된다. 또 기능을 추가할 때, 만들어서 끼워 넣으면 된다.
안 쓸 이유가 없다. 무조건 OOP로 프로그램을 만드는 게 답이다.
Class and Object
how to >> 프로그램이 객체들의 조합으로 만들어짐을 배웠다. 그럼 객체는 뭘로 만들까? 정답은 클래스이다.
different class and object >> 클래스란, 객체를 만들기 위한 설계도이다. 해당 설계도를 통해 만들어진 무언가! 이를 객체 또 다른 표현으로 인스턴스(instance)라 한다.
프로그램을 만들려면 여러 객체가 필요하다. 여러 객체를 만들려면, 객체별 클래스가 필요하다. 결과적으로, 프로그램을 만들기 위해서는 클래스를 잘 만들어야 한다.
Class design and implement
structure >> 클래스를 잘 만들려면 그 구조를 알아야 한다. 클래스는 두 영역으로 나뉜다. 상태를 정의하는 필드(fields)와 동작을 정의하는 메소드(methods)이다.
example >> 고양이를 클래스로 설계해보자. 아래와 같이 클래스를 도식화 한것을 클래스 다이어그램(class diagram)이라 한다
implement example >> 이제 이를 코드로 구현해야 한다. 왜? 그래야 객체를 만들 수 있다.
class implement >> 이를 코드로 구현(작성)하면 아래와 같습니다. 특별히 주의할 점으로는, 메소드 앞 public static 키워드가 없다는 점입니다.class Cat { /* 필드(상태) 영역 */ String name; // 이름 String breeds; // 품종 double weight; // 무게 /* 메소드(동작) 영역 */ void claw() { System.out.println("할퀴기!!"); } void meow() { System.out.println("야옹!!"); } }
CODE
/* Main 클래스 */ public class Main { public static void main(String[] args) { // Dog 객체 생성 Dog d = new Dog(); // Dog 객체 필드 값 출력 System.out.printf("이름: %s\n", d.name); System.out.printf("품종: %s\n", d.breeds); System.out.printf("나이: %s\n", d.age); } } /* Dog 클래스 */ class Dog { /* 1. 필드 영역을 작성하시오. */ String name; String breeds; int age; /* 2. 메소드 영역을 추가하시오. */ void wag(){ } void bark(){ } }
class code example >> 클래스 다이어그램을 통해 코드를 완성하였다면, 이제 객체를 만들 수 있습니다.
/* Dog(개) 클래스 예 */ class Dog { /* 필드 영역 */ String name; // 이름 double weight; // 무게 /* 메소드 영역 */ void bark() { System.out.println("멍멍!"); } }
make object >> 위 Dog 클래스의 객체(인스턴스)를 만드는 코드는 아래와 같습니다.
// Dog 객체를 생성 new Dog();
일반적으로는 만든 객체를 다시 사용키 위해, 다음과 같이 변수로 이름을 붙여줍니다.'
// 객체 생성 후, dog1 변수에 연결 Dog dog1 = new Dog(); // 비교: 일반 변수 int score = 86;
dot operator >> 생성된 객체는 연결된 변수에 닷(.) 연산을 함으로써, 접근할 수 있습니다.
// dog1 변수에 연결된 객체에 접근, name 변경. dog1.name = "멍무이"; // dog1 변수에 연결된 객체에 접근, weight 변경. dog1.weight = 4.27; // 필드 값 출력 System.out.printf("이름: %s\n", dog1.name); System.out.printf("무게: %.2fkg\n", dog1.weight);
CODE
/* CatTest 클래스 */ public class CatTest { public static void main(String[] args) { // Cat 객체 생성 Cat c = new Cat(); /* 1. 객체의 필드 값을 변경하시오. */ c.name = "네로"; c.breeds = "페르시안"; c.age = 3; // Dog 객체 필드값 출력 System.out.printf("이름: %s\n", c.name); System.out.printf("품종: %s\n", c.breeds); System.out.printf("나이: %s\n", c.age); } } /* Cat 클래스 */ class Cat { String name; // 이름 String breeds; // 품종 int age; // 나이 void claw() { System.out.println("할퀴기!!"); } void meow() { System.out.println("야옹~"); } }
lots object?? >> 하나의 잘 설계된 클래스로, 여러 개의 객체를 만들 수 있습니다. 이는 마치, 붕어빵틀로 여러개의 붕어빵을 만드는 것과 같습니다.
over two objects >> 아래는 Bicycle 클래스를 통해 두 객체를 생성하는 예입니다.// 자전거 객체를 만들고, b1 변수에 대입 Bicycle b1 = new Bicycle(); // 자전거 객체 b2 생성 Bicycle b2 = new Bicycle();
생성된 객체는 변수를 통해 접근할 수 있습니다. 여기에 닷 연산자(.)를 추가하면 해당 객체의 필드에 접근할 수 있습니다.
// 자전거 객체 b2의 필드값 초기화 b2.name = "전기 자전거"; b2.weight = 25.34; b2.price = 799000;
CODE
/* 메인 클래스 */ public class BicycleTest { public static void main(String[] args) { // 자전거 객체 생성 Bicycle b1 = new Bicycle(); // 객체 필드값 초기화 b1.name = "로드형 자전거"; b1.weight = 7.25; b1.price = 326000; // 객체 정보 출력 System.out.printf("b1->{%s, %.2f, %d}\n", b1.name, b1.weight, b1.price); /* 1. 새 자전거 객체 b2를 생성하시오. */ Bicycle b2 = new Bicycle(); /* 2. b2 객체의 필드를 초기화하시오. */ b2.name = "산악형 자전거"; b2.weight = 10.68; b2.price = 429000; /* 3. b2 객체 정보를 출력하시오. */ System.out.printf("b2->{%s, %.2f, %d}\n", b2.name, b2.weight, b2.price); } } /* 자전거 클래스 */ class Bicycle { /* 필드 */ String name; // 이름 double weight; // 무게 int price; // 가격 /* 메소드 */ void move() { System.out.println("자전거를 타고 이동합니다."); } void horn() { System.out.println("따르르릉! 지나갈게요~"); } }
order to object >> 클래스를 통해 생성된 객체. 이를 인스턴스(instance)라 합니다. 아래는 Cat 인스턴스의 메소드인 meow()를 수행시키는 코드 예입니다.
Cat cat1 = new Cat(); cat1.meow(); // "야옹~"
이렇게 객체에 특정 동작을 수행시키는 것. 이를 “인스턴스 메소드 호출”이라 합니다.
CODEpublic class CatTest2 { public static void main(String[] args) { // 고양이 객체 c1 생성 Cat cat1 = new Cat(); Cat cat2 = new Cat(); // 메소드 호출 cat1.meow(); cat2.meow(); /* 1. 할퀴기 메소드를 호출하시오. */ cat1.claw(); cat2.claw(); } } /* 고양이 클래스 */ class Cat { /* 필드(상태) */ String name; // 이름 String breeds; // 품종 int age; // 나이 /* 메소드(동작) */ void meow() { System.out.println("야옹~"); } void claw() { /* 2. 할퀴기 메소드를 완성하시오. */ System.out.println("할퀴기!! 슥샥!"); } }
field area >> 필드의 활동 영역은 클래스 전체입니다. 따라서, 메소드 호출 시 필드를 사용할 수 있습니다.
class Dog { String name; int age; void bark() { // 필드 name을 사용 System.out.println(name + "의 멍멍!"); } }
class scope >> 이러한 변수의 활동영역을 스코프(scope)라 합니다. 따라서 필드의 활동영역은 “클래스 스코프”가 됩니다.
CODEpublic class CatTest3 { public static void main(String[] args) { // 두 고양이 객체 생성 Cat cat1 = new Cat(); Cat cat2 = new Cat(); // 객체 필드 초기화 cat1.name = "네로"; cat2.name = "나비"; // 두 고양이의 야옹~ cat1.meow(); cat2.meow(); // 두 고양이의 할퀴기! cat1.claw(); cat2.claw(); } } /* 고양이 클래스 */ class Cat { /* 필드(상태) 영역 */ String name; // 이름 String breeds; // 품종 int age; // 나이 /* 메소드(동작) 영역 */ void meow() { System.out.printf("[%s]의 야옹~\n", name); } void claw() { /* 1. claw 메소드를 완성하시오. */ System.out.printf("[%s]의 할퀴기! 샥샥~", name); } }
method scope >> 파라미터와 지역변수는 메소드 스코프를 가집니다. 다시 말해, 이들의 활동영역은 자신이 속한 메소드 내부입니다.
local variable >> 여기서 지역변수란, 메소드 내부에 선언된 변수입니다.class DrinkMachine { String output; // 필드 output 선언 void pushButton(int num) { // 파라미터 num 선언 // 지역변수 drinks 선언 String[] drinks = {"콜라", "사이다", "맥주"}; output = drinks[num]; } void printOutput() { System.out.println(output); } }
scope type
클래스 스코프: 필드
메소드 스코프: 파라미터, 지역변수
CODEpublic class DrinkMachineTest { public static void main(String[] args) { // 객체 생성 DrinkMachine machine1 = new DrinkMachine(); DrinkMachine machine2 = new DrinkMachine(); // 음료 뽑기 machine1.pushButton(1); machine2.pushButton(2); // 음료 확인 machine1.printOutput(); machine2.printOutput(); } } class DrinkMachine { /* 필드 */ String output; /* 메소드 */ void pushButton(int num) { String[] drinks = {"콜라", "사이다", "맥주"}; output = drinks[num]; } void printOutput() { System.out.println(output); } }
CODEpublic class SquareTest { public static void main(String[] args) { /* 객체 생성 */ Square s = new Square(); /* 필드 초기화(값 변경) */ s.length = 4; /* 결과 출력 */ System.out.printf("한 변의 길이가 %d인 정사각형의 넓이: %d", s.length, s.area()); } } /* 정사각형 클래스 구현 */ class Square { // fields int length; // methods int area() { return length * length; } }