일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 부스트캠프
- Boostcamp AI
- string
- Coursera
- 알고리즘
- 데이터과학
- 파이썬
- 데이터 사이언스
- 코딩테스트
- 클린코드
- Clean Code
- 클린코드 파이썬
- 문자열
- softeer
- Python
- 프로그래머스
- 오블완
- data science methodology
- 깨끗한 코드
- IBM
- Data Science
- programmers
- 소프티어
- 코세라
- 자바
- Java
- 데이터사이언스
- AI Mathematics
- 코테
- 티스토리챌린지
- Today
- Total
떼닝로그
[CS] 객체 지향 프로그래밍의 특징 본문
객체 지향 프로그래밍(Object-Oriented Programming, OOP)
- 프로그래밍에서 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체로 만들고, 객체들간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법
- 여러 독립적인 부품들의 조합, 즉 객체들의 유기적인 협력과 결합으로 파악하고자 하는 컴퓨터 프로그래밍의 패러다임
- 객체 : 클래스의 인스턴스나 배열. 속성과 기능을 가지는 프로그램 단위. 모든 실재하는 대상
- 객체 지향 프로그래밍의 장점 : 보다 유연하고 변경이 용이하게 만들기 가능, 코드의 변경을 최소화하고 유지보수를 하는 데 유리, 코드의 재사용을 통한 반복적인 코드 최소화, 코드를 최대한 간결하게 표현 가능, 인간 친화적이고 직관적인 코드 작성에 용이
객체 지향 프로그래밍의 특징
추상화 (Abstraction)
- 추상화 : 객체의 공통적인 속성과 기능을 추출하여 정의하는 것
- 자동차와 오토바이는 모두 Vehicle이라는 특징을 가지며, start, moveForward, moveBackward의 공통적인 기능을 수행할 수 있음
- 아래는 Vehicle Interface
public interface Vehicle{
public abstract void start();
void moveForward(); // public abstract 생략 가능
void moveBackward();
}
- 아래는 Car class
public class Car implements Vehicle{ // 이동수단을 구체화한 자동차 클래스
@Override
public void moveForward(){
System.out.println("자동차 전진");
}
@Override
public void moveBackward(){
System.out.println("자동차 후진");
}
}
- 아래는 Motorbike class
public class MotorBike implements Vehicle{
@Override
public void moveForward(){
System.out.println("오토바이 전진");
}
@Override
public void moveBackward(){
System.out.println("오토바이 후진");
}
}
- 이런 것을 객체 지향 프로그래밍에서는 역할과 구현의 분리라고 함
- 이 부분이 다형성과 함께 유연하고 변경이 용이한 프로그램을 설계하는 데 가장 핵심적인 부분
- 역할에 해당하는 부분이 인터페이스를 통해 추상화될 수 있음
상속 (Inheritance)
- 상속 : 기존의 클래스를 재활용하여 새로운 클래스를 작성하는 자바의 문법 요소
- 상위 클래스로부터 확장된 여러 개의 하위 클래스들이 모두 상위 클래스의 속성과 기능들을 간편하게 사용할 수 있도록 함
- 공유하는 속성과 기능들을 한 번만 정의해두고 재사용할 수 있어, 반복적인 코드 최소화하고 공유하는 속성과 기능에 간편하게 접근 가능
- 아래는 Vehicle class
public class Vehicle { //추상화를 통한 상위클래스 정의
String model;
String color;
int wheels;
void moveForward() {
System.out.println("전진합니다.");
}
void moveBackward() {
System.out.println("후진합니다.");
}
}
- 아래는 각각 Car, MotorBike class
// Car
public class Car extends Vehicle {
boolean isConvertible;
void openWindow(){
System.out.println("모든 창문 열기");
}
}
// MotorBike
public class MotorBike extends Vehicle {
boolean isRaceable;
// 메서드 오버라이딩 -> 기능 재정의
@Override
void moveForward() {
System.out.println("오토바이가 앞으로 전진합니다.");
}
public void stunt(){
System.out.println("오토바이로 묘기를 부립니다.");
}
}
- Car와 MotorBike class의 공통적인 속성과 기능들을 추출(추상화)하여 Vehicle 클래스 정의
- extends 키워드를 통해 각각의 하위 클래스로 확장하여 해당 기능과 속성들을 반복적으로 정의해야 하는 번거로움 제거
- 공통적인 코드의 변경이 있는 경우, 상위 클래스에서 단 한 번의 수정으로 모든 클래스에 변경 사항 반영
- 각 클래스의 맥락에 맞게 메서드 오버라이딩(method overriding)을 사용하여 내용 재정의 가능
- 인터페이스를 통한 구현과 상속 모두 상위 클래스-하위 클래스의 관계를 전제하면서 공통적인 속성과 기능 공유
- 상속은 하위 클래스의 속성과 기능들을 하위 클래스에서 그대로 받아 사용하거나 오버라이딩을 통해 선택적으로 재정의하여 사용 가능
- 인터페이스를 통한 구현은 반드시 인터페이스에 정의된 추상 메서드의 내용이 하위 클래스에서 정의되어야 함
- 상속 관계의 경우, 인터페이스를 사용하는 구현에 비해 추상화의 정도가 낮음.
다형성 (Polymorphism)
- 다형성 : 어떤 객체의 속성이나 기능이 그 맥락에 따라 다른 역할을 수행할 수 있는 객체 지향의 특성
- 메서드 오버라이딩, 메서드 오버로딩이 다형성의 대표적인 예시
- 객체 지향 프로그래밍에서 다형성이란, 한 타입의 참조변수를 통해 여러 타입의 객체를 참조할 수 있도록 만든 것.
- 즉, 상위 클래스 타입의 참조변수로 하위 클래스의 객체를 참조할 수 있도록 하는 것.
- 아래는 다형성 개념을 활용하여 객체를 생성하는 방법에 대한 코드
public class Main {
public static void main(String[] args) {
// 원래 사용했던 객체 생성 방식
Car car = new Car();
MotorBike motorbike = new MotorBike();
// 다형성을 활용한 객체 생성 방식
Vehicle car2 = new Car();
}
}
- 다형성을 사용하면 여러 종류의 객체를 배열로 다루는 일이 가능해짐
public class Main {
public static void main(String[] args){
// 상위 클래스 타입의 객체 배열 생성
Vehicle vehicles[] = new Vehicle[2];
vehicles[0] = new Car();
vehicles[1] = new MotorBike();
for (Vehicle vehicle : vehicles) {
System.out.println(vehicle.getClass()); // 각각의 클래스를 호출해주는 메서드
}
}
}
// 출력값
class Car;
class MotorBike;
- 다형성을 활용하면 하나의 타입만으로 여러 가지 타입의 객체를 참조할 수 있어, 보다 간편하고 유연하게 코드 작성 가능
- 하나의 객체가 다른 객체의 속성과 기능에 접근하여 어떤 기능을 사용할 때, 이것을 A 클래스는 B 클래스에 의존한다 라고 표현
- 객체들 간의 결합도가 높은 상태는 객체 지향적인 설계를 하는 데 매우 불리
- 객체 지향 프로그래밍은 설계할 때 역할과 구현을 구분하여 객체들 간의 직접적인 결합을 피하고, 느슨한 관계 설정을 통해 보다 유연하고 변경이 용이한 프로그램 설계를 가능하게 만듦
// Vehicle 인터페이스
public interface Vehicle { // 이동수단의 역할 정의
void moveForward();
void moveBackward();
}
// Car 클래스
public class Car implements Vehicle { // 이동수단 인터페이스를 구현
@Override
public void moveForward(){
System.out.println("자동차가 앞으로 전진합니다.");
}
@Override
public void moveBackward() {
System.out.println("자동차가 뒤로 후진합니다.");
}
}
// MotorBike 클래스
public class MotorBike implements Vehicle { // 이동수단 인터페이스를 구현
@Override
public void moveForward() {
System.out.println("오토바이가 앞으로 전진합니다.");
}
@Override
public void moveBackward() {
System.out.println("오토바이가 뒤로 후진합니다.");
}
}
// Driver 클래스
public class Driver {
void drive(Vehicle vehicle) { // 매개변수로 인터페이스 타입의 참조변수를 전달
vehicle.moveForward();
vehicle.moveBackward();
}
}
// Main 실행 클래스
public class Main {
public static void main(String[] args) {
Car car = new Car();
MotorBike motorBike = new MotorBike();
Driver driver = new Driver();
driver.drive(car);
driver.drive(motorBike);
}
}
// 출력값
자동차가 앞으로 전진합니다.
자동차가 뒤로 후진합니다.
오토바이가 앞으로 전진합니다.
오토바이가 뒤로 후진합니다.
- Vehicle 인터페이스를 통해 이동 수단의 역할을 추상화하고, 각각 Car 클래스와 MotorBike 클래스에서 기능 구현
- Driver 클래스는 drive 메서드로 전달되는 매개변수의 타입을 상위 클래스인 인터페이스 타입 Vehicle로 설정
- Vehicle 인터페이스를 통해 Driver 클래스와 Car, MotorBike 클래스 간의 결합도가 낮아짐
- Driver 클래스는 더 이상 각각의 클래스 내부의 변경이나 다른 객체가 새롭게 교체되는 것을 신경 쓰지 않아도, 인터페이스에만 의존하여 수정이 있을 때마다 코드 변경을 하지 않아도 됨
캡슐화 (Encapsulation)
- 캡슐화 : 클래스 안에 서로 연관 있는 속성과 기능들을 하나의 캡슐로 만들어 데이터를 외부로부터 보호하는 것
- 캡슐화를 하는 대표적인 이유 두 가지 : 데이터 보호, 데이터 은닉
- 데이터 보호 (data protection) : 외부로부터 클래스에 정의된 속성과 기능들을 보호
- 데이터 은닉 (data hiding) : 내부의 동작을 감추고 외부에는 필요한 부분만 노출
- 캡슐화의 목적 : 외부로부터 클래스에 정의된 속성과 기능들을 보호하고, 필요한 부분만 외부로 노출될 수 있도록 하여 각 객체 고유의 독립성과 책임 영역을 안전하게 지키고자 함
- 접근 제어자(access modifier)를 클래스 또는 클래스의 내부의 멤버들에 사용하여 해당 클래스나 멤버들을 외부에서 접근하지 못하도록 접근을 제어함
- 자바에는 public, default, protected, private로 총 네 가지 종류의 접근 제어자가 존재
- 자바의 캡슐화를 구현하기 위해 getter/setter를 사용하여 선택적으로 외부에 접근을 허용할 속성과 그렇지 않을 속성을 설정
- 캡슐화를 활용하여 객체의 자율성, 즉 하나의 객체가 해당 객체의 속성과 기능에 대한 독자적인 책임을 담당하도록 만들고, 이를 통해 객체 간의 결합도를 낮게 유지 가능
// Car 클래스
public class Car {
private String model;
private String color;
public Car(String model, String color) {
this.model = model;
this.color = color;
}
private void startEngine() {
System.out.println("시동을 겁니다.");
}
private void moveForward() {
System.out.println("자동차가 앞으로 전진합니다.");
}
private void openWindow() {
System.out.println("모든 창문을 엽니다.");
}
public void operate() { // 앞서 driver 클래스에 정의된 메서드들 이동하여 메서드 추출
startEngine();
moveForward();
openWindow();
}
}
// Driver 클래스
public class Driver {
private String name;
private Car car;
public Driver(String name, Car car) {
this.name = name;
this.car = car;
}
public String getName() {
return name;
}
public void drive() {
car.operate(); // Car 클래스에 있는 메서드를 단순하게 호출
}
}
// Main 실행 클래스
public class Main {
public static void main(String[] args) {
Car car = new Car("테슬라 모델X", "레드");
Driver driver = new Driver("김코딩", car);
driver.drive();
}
}
// 출력값
시동을 겁니다.
자동차가 앞으로 전진합니다.
모든 창문을 엽니다.
- 캡슐화를 활용하면, 객체 내부 동작의 외부로의 노출을 최소화하여 각 객체의 자율성을 높이고, 이를 통해 객체 간 결합도를 낮춰 객체 지향의 핵심적인 이점을 잘 살릴 수 있음
참조)
https://upcake.tistory.com/418
'개발로그 > 기타 이론 정리' 카테고리의 다른 글
[Python] " is None " vs " == None " (1) | 2024.11.27 |
---|---|
[CS] 객체 지향 설계의 SOLID 규칙 (OO 5원칙) (2) | 2024.11.08 |
[C#] Virtual(가상) vs Abstract(추상) vs Interface(인터페이스) (4) | 2024.10.08 |
[Python] Python 기술 면접 대비 (2) | 2024.04.24 |