자바 OOP 란 철학과 기법에 대한 Do it! 알고리즘 입문: 자바 편 (6)[책리뷰 & Book review]
객체 지향 프로그래밍(Object-Oriented Programming, OOP)은 프로그래밍 패러다임 중 하나로, 객체라는 개념을 중심으로 프로그램을 작성하는 방법론입니다.
OOP의 핵심 철학은 '실세계의 사물을 객체로 모델링하고, 이 객체들 간의 상호작용을 통해 로직을 구현하는 것'입니다.
자바는 대표적인 객체 지향 프로그래밍 언어로,
OOP의 주요 원칙인 캡슐화, 상속, 다형성, 추상화를 모두 지원합니다.
예를 들어, '자동차'라는 개념을 객체 지향 프로그래밍으로 표현해 보겠습니다.
java
// 자동차 클래스 정의
public class Car {
// 필드 (상태)
private String color;
private int speed;
// 생성자
public Car(String color) {
this.color = color;
this.speed = 0;
}
// 메소드 (행동)
public void accelerate(int amount) {
speed += amount;
}
public void decelerate(int amount) {
speed -= amount;
}
// getter와 setter
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSpeed() {
return speed;
}
}
위 코드는 '자동차'라는 객체를 모델링한 것입니다.
자동차는 '색상'과 '속도'라는 상태를 가지며,
'가속'과 '감속'이라는 행동을 할 수 있습니다.
이처럼 객체 지향 프로그래밍은 실세계의 객체를 프로그램에 반영하는 것을 목표로 합니다.
이제 이 '자동차' 클래스를 사용하는 예제 코드를 작성해 보겠습니다.
java
public class Main {
public static void main(String[] args) {
// Car 객체 생성
Car myCar = new Car("red");
// 가속
myCar.accelerate(10);
System.out.println("현재 속도: " + myCar.getSpeed());
// 감속
myCar.decelerate(5);
System.out.println("현재 속도: " + myCar.getSpeed());
}
}
위 코드의 동작 방식은 다음과 같습니다:
Main 클래스의 main 메소드에서 '자동차' 객체를 생성합니다.
이 객체의 색상은 'red'입니다.
'가속' 메소드를 호출하여 자동차의 속도를 10 증가시킵니다.
'감속' 메소드를 호출하여 자동차의 속도를 5 감소시킵니다.
Main ----(create)----> Car ----(accelerate)----> speed: 10
Main ----(create)----> Car ----(decelerate)----> speed: 5
위 예제에서는 OOP의 캡슐화 원칙을 활용하였습니다.
캡슐화는 객체의 상태를 직접 변경하지 않고, 메서드를 통해 변경하는 것을 의미합니다.
이를 통해 객체의 상태를 안정적으로 관리할 수 있습니다.
이외에도 상속, 다형성, 추상화 등의 원칙을 활용하면 더욱 풍부하고 유연한 프로그램을 작성할 수 있습니다.
니모닉 이란 무엇인가?
니모닉(Mnemonic)은 기억을 돕기 위해 복잡한 정보를 간략하고 이해하기 쉬운 형태로 변환하는 기법을 의미합니다.
이는 주로 긴 숫자나 복잡한 패턴을 쉽게 기억하게 돕는 데 사용됩니다.
프로그래밍에서는 주로 어셈블리어에서 사용되는데,
기계어 코드를 사람이 이해하기 쉬운 단어로 변환하는 데 사용됩니다.
예를 들어, 어셈블리어의 명령어 중 'MOV'는 '이동'이라는 단어를 나타내며, 특정 위치의 데이터를 다른 위치로 이동하는 명령을 의미합니다.
자바에서는 이와 비슷한 개념으로 '상수'를 들 수 있습니다.
상수는 변하지 않는 값을 의미하는데,
이를 특정한 이름으로 지정하여 코드의 가독성을 높이고 오류를 줄이는 데 도움이 됩니다.
예를 들어, 원주율 값을 상수로 지정하는 코드를 작성해보겠습니다.
java
public class Main {
// 원주율 값을 상수로 지정
public static final double PI = 3.141592;
public static void main(String[] args) {
// 원의 둘레를 계산
double radius = 10.0;
double circumference = 2 * PI * radius;
System.out.println("원의 둘레: " + circumference);
}
}
위 코드의 동작 방식은 다음과 같습니다:
Main 클래스에서 원주율 값을 상수 PI로 지정합니다.
main 메소드에서 반지름이 10.0인 원의 둘레를 계산하고, 그 결과를 출력합니다. 이때 원의 둘레를 계산하는 공식에는 상수 PI가 사용됩니다.
도식화하면 다음과 같습니다:
Main ----(define PI)----> 3.141592
Main ----(calculate circumference)----> 2 * PI * radius ----(print)----> "원의 둘레: " + circumference
위 예제에서는 상수 PI를 사용하여 원주율 값을 코드에서 쉽게 인식하고 사용할 수 있게 하였습니다. 이는 코드의 가독성을 높이고, 원주율 값이 변해야 할 경우 해당 값을 한 곳에서만 변경하면 되므로 유지 보수성도 향상합니다. 이처럼 '상수'는 자바에서 '니모닉'과 비슷한 역할을 하는 개념입니다.
추상화 class 와 interface는 어떤 차이점이 있는가?
추상 클래스와 인터페이스는 비슷해 보이지만 사용 목적과 특성에는 몇 가지 차이점이 있습니다:
추상 클래스(Abstract Class)
추상 클래스는 일반 메서드(구현이 있는 메서드)와 추상 메서드(구현이 없는 메서드) 모두 가질 수 있습니다.
상속을 통해 추상 클래스를 확장하고 추상 메서드를 구현하게 됩니다.
상속은 단일 상속만 가능하므로, 한 클래스는 하나의 추상 클래스만 확장할 수 있습니다.
상태를 표현하는 필드를 가질 수 있습니다.
인터페이스(Interface)
인터페이스는 모든 메소드가 기본적으로 추상 메서드입니다(자바 8부터 디폴트 메서드와 정적 메서드를 가질 수 있게 되었습니다).
인터페이스는 '구현(implements)' 받아야 하며, 한 클래스는 여러 인터페이스를 구현할 수 있습니다.
인터페이스는 상태를 표현하는 필드를 가질 수 없습니다(상수만 가질 수 있습니다).
먼저 추상 클래스와 인터페이스를 이해하는 데 도움이 될 예제 코드를 작성하겠습니다.
추상 클래스
java
public abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public abstract void sound(); // 추상 메소드
public void introduce() { // 일반 메소드
System.out.println("이 동물의 이름은 " + this.name + "입니다.");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void sound() {
System.out.println("Dog is barking");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("멍멍이");
dog.introduce();
dog.sound();
}
}
위 코드의 동작 방식은 다음과 같습니다:
Animal이라는 추상 클래스를 정의합니다. 이 클래스는 name이라는 필드와 sound()라는 추상 메서드, 그리고 introduce()라는 일반 메서드를 가지고 있습니다.
Dog 클래스는 Animal 클래스를 상속받습니다. 따라서 Dog 클래스는 sound() 메서드를 반드시 구현해야 하며, introduce() 메서드를 그대로 사용하거나 필요에 따라 재정의할 수 있습니다.
Main 클래스에서는 Dog 객체를 생성하고, introduce()와 sound() 메소드를 호출합니다.
인터페이스
java
public interface Animal {
void sound(); // 추상 메소드
}
public class Dog implements Animal {
@Override
public void sound() {
System.out.println("Dog is barking");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound();
}
}
위 코드의 동작 방식은 다음과 같습니다:
Animal 이라는 인터페이스를 정의합니다. 이 인터페이스는 sound()라는 추상 메서드를 가지고 있습니다.
Dog 클래스는 Animal 인터페이스를 구현합니다. 따라서 Dog 클래스는 sound() 메서드를 반드시 구현해야 합니다.
Main 클래스에서는 Dog 객체를 생성하고, sound() 메서드를 호출합니다.
이처럼 추상 클래스와 인터페이스는 모두 추상 메소드를 정의하는 데 사용
객체는 정확하게 무엇인가?
자바에서 객체(Object)는 클래스로부터 생성된 인스턴스를 의미합니다.
객체는 상태와 행동을 가집니다.
상태는 필드(Field)를 통해 표현되며, 행동은 메소드(Method)를 통해 표현됩니다.
객체가 키-값 쌍으로만 구성된다는 설명은 일반적으로 JavaScript와 같은 언어에서 사용하는 객체 모델에 가깝습니다.
하지만 자바에서 객체는 키-값 쌍이 아닌 필드와 메소드로 구성됩니다.
객체 생성과 사용에 대한 예제를 통해 설명하겠습니다.
java
public class Dog {
// 필드 (상태 표현)
private String name;
private int age;
// 생성자
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
// 메소드 (행동 표현)
public void bark() {
System.out.println(name + "가 짖습니다: 멍멍!");
}
public void showAge() {
System.out.println(name + "의 나이는 " + age + "살입니다.");
}
}
public class Main {
public static void main(String[] args) {
// 객체 생성
Dog myDog = new Dog("멍멍이", 3);
// 객체 사용
myDog.bark();
myDog.showAge();
}
}
위 코드의 동작 방식은 다음과 같습니다:
Dog 클래스는 name과 age라는 필드(상태)와 bark(), showAge()라는 메서드(행동)를 가지고 있습니다.
Main 클래스에서는 Dog 클래스로부터 myDog라는 객체를 생성하고, bark()와 showAge() 메서드를 호출하여 사용합니다.
이처럼 자바에서 객체는 클래스의 인스턴스로, 상태를 나타내는 필드와 행동을 나타내는 메소드로 구성됩니다. 이를 통해 객체 지향 프로그래밍의 핵심 원칙인 캡슐화, 상속, 다형성 등을 구현할 수 있습니다.
인터페이스(Interface) 범위는 어디까지인가?
인터페이스(Interface)는 클래스와는 다르게 독립적인 역할을 합니다.
인터페이스는 메소드의 시그니처를 정의하고, 이를 구현하는 클래스는 이 인터페이스를 따라 메서드를 구현해야 합니다. 한 클래스가 인터페이스를 구현(Implements)하면, 그 클래스는 인터페이스에서 정의된 모든 메서드를 구현해야 합니다.
인터페이스는 한 클래스에 종속되지 않으며, 여러 클래스에서 구현할 수 있습니다.
따라서 인터페이스는 범용적으로 사용할 수 있습니다.
인터페이스를 통해 다른 클래스와의 관계를 정의하거나,
다양한 클래스가 같은 동작을 수행하도록 강제하는 역할을 합니다.
인터페이스 사용에 대한 예제를 통해 설명하겠습니다.
java
// 인터페이스 정의
public interface Animal {
void sound(); // 추상 메소드
}
// Dog 클래스에서 Animal 인터페이스 구현
public class Dog implements Animal {
@Override
public void sound() {
System.out.println("Dog is barking");
}
}
// Cat 클래스에서 Animal 인터페이스 구현
public class Cat implements Animal {
@Override
public void sound() {
System.out.println("Cat is meowing");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
Animal myCat = new Cat();
myDog.sound(); // "Dog is barking"
myCat.sound(); // "Cat is meowing"
}
}
위 코드의 동작 방식은 다음과 같습니다:
Animal이라는 인터페이스를 정의하고, sound()라는 추상 메서드를 선언합니다.
Dog와 Cat 클래스는 Animal 인터페이스를 구현하므로 sound() 메서드를 반드시 구현해야 합니다.
Main 클래스에서는 Dog 객체와 Cat 객체를 생성하고, sound() 메서드를 호출합니다. 이때 Animal 타입의 변수로 Dog와 Cat 객체를 참조하고 있으므로, 각 객체의 sound() 메서드가 실행됩니다.
'컴퓨터공부 > 책리뷰 & book review' 카테고리의 다른 글
Do it! 알고리즘 입문: 자바 편 (8)[책리뷰 & Book review] (1) | 2024.01.30 |
---|---|
Do it! 알고리즘 입문: 자바 편 (7)[책리뷰 & Book review] (1) | 2024.01.30 |
Do it! 알고리즘 입문: 자바 편 (5)[책리뷰 & Book review] (1) | 2024.01.30 |
Do it! 알고리즘 입문: 자바 편 (4)[책리뷰 & Book review] (1) | 2024.01.30 |
댓글