새소식

Java

[Java] 객체 지향 프로그래밍

  • -

 

객체 지향 프로그래밍

 

1)    객체 지향 프로그래밍(Object-Oriented Programming, OOP)의 개념

 

현실 세계의 사물을 프로그램으로 모델링하는 프로그래밍 방법입니다.

이 방법은 프로그램을 개별적인 객체들의 집합으로 구성하고, 객체들 간의 상호작용을 중심으로 프로그램을 구성합니다.

 

 

 

2)    객체 지향 프로그래밍의 장점

 

① 모듈화

객체지향 프로그래밍은 코드를 독립적인 모듈인 객체로 나누어 개발할 수 있습니다.
이로 인해 코드의 재사용성이 증가하고 유지보수가 용이해집니다.

 

② 코드 재사용

상속을 통해 부모 클래스의 속성과 동작을 자식 클래스에서 재사용할 수 있습니다. 
이를 통해 중복 코드를 피하고 개발 시간을 절약할 수 있습니다.

 

③ 유지보수성

수정이 필요한 부분을 객체 단위로 수정하거나 확장할 수 있으므로 전체 코드의 영향을 최소화할 수 있습니다.

 

④ 확장성

객체지향 프로그래밍은 계층 구조를 가질 수 있으며, 
새로운 클래스를 추가하거나 기존 클래스를 변경하여 기능을 확장하기 쉽습니다..

 

⑤ 다형성

다형성은 같은 이름의 메서드를 다양한 형태로 사용할 수 있게 합니다.
이는 유연한 코드 작성과 코드의 가독성을 높여줍니다.

 

 

 

 

3)    객체 지향 프로그래밍의 단점

 

① 어려움

객체지향 프로그래밍은 객체, 클래스, 상속 등의 개념을 이해하고 활용해야 합니다.
초기 학습 곡선이 다소 높을 수 있으며, 객체지향적인 사고 방식을 익히는 데 시간이 필요할 수 있습니다.

 

오버 헤드

코드의 모듈화와 재사용성을 강조하기 때문에 일부 경우에 작은 규모의 문제에 비해 더 많은 코드가 필요할 수 있습니다. 
이로 인해 일부 성능 저하(속도 느림)가 발생할 수 있습니다.

 

③ 설계의 복잡성

좋은 객체 모델링과 설계가 필요합니다. 객체 간의 관계, 캡슐화, 상속 등을 고려하여 복잡한 설계를 수행해야 합니다.

 

 

 

 

 

 

4)    클래스와 객체

 

① 클래스 ( Class )

클래스는 객체를 정의하기 위한 템플릿이며, 객체를 생성하기 위한 구조를 제공합니다.
클래스는 객체의 속성(멤버 변수)과 동작(메서드)을 정의합니다.

 

 

② 객체 ( Object )

클래스의 인스턴스로, 실제로 메모리에 할당된 데이터입니다.
객체는 클래스에서 정의한 속성과 동작을 가지며, 다른 객체와 상호작용할 수 있습니다.

 

 

 

 

 

 

5)    객체 지향 프로그래밍의 주요 개념

 

① 추상화 ( Abstraction )

 

복잡한 시스템을 단순화하고 핵심 개념을 강조하기 위해 구체적인 세부 정보를 숨기고 중요한 특성, 동작에 집중하는 과정


불필요한 세부 사항들은 제거하고 가장 본질적이고 공통적인 부분만을 추출하여 표현

 

 

 

 

<예시>
포켓몬은 다양한 종류가 있지만, 모든 포켓몬은 몇 가지 공통된 특성과 동작을 가지고 있습니다. 추상화를 통해 포켓몬의 핵심 개념을 강조할 수 있습니다.

public abstract class
Pokemon {
private String name;
private int level;

public Pokemon(String name, int level) {
this.name = name;
this.level = level;
}

public abstract void attack();
public abstract void evolve();
// ...

// Getter and setter methods for name and level
// ...
}

"포켓몬" 추상 클래스가 포켓몬의 이름과 레벨을 나타내는 속성을 가지고 있습니다.
또한, attack()evolve() 같은 추상 메서드를 선언하여
포켓몬마다 구체적으로 구현되어야 하는 동작을 정의하고 있습니다
.
public class Pikachu extends Pokemon {
public Pikachu(String name, int level) {
super(name, level);
}

@Override
public void attack() {
System.out.println("Pikachu uses Thunderbolt!");
// 구체적인 공격 동작 구현
}

@Override
public void evolve() {
System.out.println("Pikachu is evolving into Raichu!");
// 구체적인 진화 동작 구현
     }
}

Pikachu 클래스는 Pokemon 추상 클래스를 상속받아 구현한 것입니다.
attack()evolve() 메서드를 구체적으로 구현하여 Pikachu의 공격과 진화 동작을 표현하고 있습니다.

이제 다른 포켓몬도 동일한 방식으로 구현할 수 있습니다.
이렇게 추상화를 통해 포켓몬의 공통된 특성과 동작을 강조하고,
실제 포켓몬 객체들은 이 추상화된 모델을 기반으로 구현됩니다.

 

 

 

 

 

② 상속 ( Inheritance )

 

상속은 한 클래스가 다른 클래스의 특성(속성과 메서드)을 물려받아 사용할 수 있도록 해줍니다.

이를 통해 코드의 재사용성과 구조화된 계층 구조를 형성할 수 있습니다. 

 

<예시>
public class Pokemon {
private String name;
private int level;

public Pokemon(String name, int level) {
this.name = name;
this.level = level;
}

public void attack() {
System.out.println("Pokemon attacks!");
}

// Getter and setter methods for name and level
// ...
}

먼저, 기본적인 포켓몬을 나타내는 Pokemon 클래스를 정의했습니다.
이 클래스는 포켓몬의 이름과 레벨을 나타내는 속성과
attack() 메서드를 가지고 있습니다.
public class Pikachu extends Pokemon {
public Pikachu(String name, int level) {
super(name, level);
}

@Override
public void attack() {
System.out.println("Pikachu uses Thunderbolt!");
}

public void electricAttack() {
System.out.println("Pikachu uses Electric Attack!");
     }
}

Pikachu 클래스는 Pokemon 클래스를 상속받아 구현한 것입니다.
extends 키워드를 사용하여 상속 관계를 선언합니다.

Pikachu 클래스는 Pokemon 클래스의 모든 속성과 메서드를 물려받으며,
필요한 경우 메서드를 재정의(오버라이딩)할 수 있습니다.

Pikachu 클래스에서는 attack() 메서드를 재정의하여 Pikachu의 공격 동작을 표현했습니다. 
또한, electricAttack() 메서드를 추가로 정의하여 Pikachu의 특정한 전기 속성 공격을 구현했습니다.
** Charmander = 파이리 **

public class
Charmander extends Pokemon {
public Charmander(String name, int level) {
super(name, level);
}

@Override
public void attack() {
System.out.println("Charmander uses Ember!");
}

public void fireAttack() {
System.out.println("Charmander uses Fire Attack!");
     }
}

상속을 통해 다른 포켓몬 클래스도 비슷한 방식으로 구현할 수 있습니다.
예를 들어, Charmander 클래스(파이리)는 Pokemon 클래스를 상속받고, 
attack() 메서드를 재정의하여 Charmander의 공격 동작을 구현할 수 있습니다.

 

 

 

 

 

③ 다형성 ( Polymorphism )

 

다형성은 하나의 인터페이스나 추상 클래스를 사용하여 서로 다른 클래스들을 동일한 타입으로 처리하는 기능

이를 통해 여러 클래스가 동일한 메서드를 갖고 있더라도 각 클래스의 고유한 동작을 수행할 수 있습니다.

 

 

<예시>
public abstract class Pokemon {
private String name;
private int level;

public Pokemon(String name, int level) {
this.name = name;
this.level = level;
}

public abstract void attack();
}

Pikachu, Charmander, Squirtle 클래스는 각각 Pokemon 클래스를 상속받아
구체적인 동작을 구현할 수 있습니다.

public class
Pikachu extends Pokemon {
public Pikachu(String name, int level) {
super(name, level);
}

@Override
public void attack() {
System.out.println("Pikachu uses Thunderbolt!");
     }
}

public class Charmander extends Pokemon {
public Charmander(String name, int level) {
super(name, level);
}

@Override
public void attack() {
System.out.println("Charmander uses Ember!");
     }
}

public class Squirtle extends Pokemon {
public Squirtle(String name, int level) {
super(name, level);
}

@Override
public void attack() {
System.out.println("Squirtle uses Water Gun!");
     }
}
Pokemon 타입의 배열을 만들고 Pikachu, Charmander, Squirtle 객체들을 담을 수 있습니다.


Pokemon[] pokemons = new Pokemon[3];
pokemons[0] = new Pikachu("Pikachu", 10);
pokemons[1] = new Charmander("Charmander", 12);
pokemons[2] = new Squirtle("Squirtle", 8);

for (Pokemon pokemon : pokemons) {
pokemon.attack();
}

Pokemon 타입의 배열을 선언하고 Pikachu, Charmander, Squirtle 객체들을 배열에 저장한 뒤,
배열을 순회하며 각 포켓몬의 attack() 메서드를 호출했습니다.

이때 각 객체의 실제 타입에 따라 오버라이딩된 메서드가 호출되어
Pikachu는 Thunderbolt를, Charmander는 Ember를, Squirtle은 Water Gun을 사용하게 됩니다.

 

 

 

 

④ 캡슐화 ( Encapsulation )

 

이터와 해당 데이터를 다루는 메서드를 하나의 단위로 묶는 것.

 

이를 통해 데이터를 보호하고 외부로부터의 접근을 제한하여 데이터의 일관성과 안정성을 유지할 수 있습니다.

 

 

<예시>
public class Pokemon {
private String name;
private int level;

public Pokemon(String name, int level) {
this.name = name;
this.level = level;
}

public void attack() {
if (level >= 10) {
System.out.println(name + " uses Special Attack!");
} else {
System.out.println(name + " uses Normal Attack!");
     }
}

public void levelUp() {
level++;
}

public String getName() {
return name;
}

public int getLevel() {
return level;
     }
}

namelevelprivate 접근 제어자로 선언되어 클래스 외부에서 직접 접근할 수 없습니다.
이를 통해 데이터의 무결성과 일관성을 유지할 수 있습니다.
public class Main {
public static void main(String[] args) {
Pokemon pikachu = new Pokemon("Pikachu", 5);
pikachu.attack(); // Pikachu uses Normal Attack!

pikachu.levelUp();
pikachu.attack(); // Pikachu uses Normal Attack!

pikachu.levelUp();
pikachu.attack(); // Pikachu uses Special Attack!

System.out.println("Name: " + pikachu.getName()); // Name: Pikachu
System.out.println("Level: " + pikachu.getLevel()); // Level: 7
     }
}

외부에서는 attack() 메서드와 levelUp() 메서드를 통해
포켓몬의 동작을 수행하고 레벨을 변경할 수 있습니다.
getName()getLevel() 메서드를 통해 포켓몬의 이름과 레벨을 조회할 수 있습니다.

 

 

 

 

 

6)    객체 지향 프로그래밍 SOLID 원칙

 

단일 책임 원칙 (Single Responsibility Principle, SRP)

각 클래스는 단 하나의 책임을 가지고 있어야 합니다.

예를 들어, 포켓몬 클래스는 포켓몬의 속성과 기능을 다루지만, 포켓몬의 전투 로직은 다른 클래스에 위임해야 합니다.

 

 

 

개방-폐쇄 원칙 (Open-Closed Principle, OCP)

포켓몬 시스템은 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 합니다.

새로운 포켓몬 종류를 추가할 때는 기존 코드를 변경하지 않고 확장할 수 있어야 합니다.

예를 들어, 포켓몬 클래스에 새로운 포켓몬을 추가할 때는 상속을 통해 새로운 클래스를 작성하여 확장할 수 있습니다.

 

 

 

리스코프 치환 원칙 (Liskov Substitution Principle, LSP)

상위 타입은 하위 타입으로 치환 가능해야 합니다.

즉, 어떤 포켓몬 클래스가 있을 때, 이를 상속하는 하위 클래스는 상위 클래스로 취급될 수 있어야 합니다.

예를 들어, 파이리 클래스와 꼬부기 클래스는 포켓몬 클래스로 치환 가능해야 합니다.

 

 

 

인터페이스 분리 원칙 (Interface Segregation Principle, ISP):

클라이언트는 자신이 사용하지 않는 인터페이스에 의존하지 않아야 합니다.

포켓몬 클래스의 인터페이스는 포켓몬의 공격 기능과 특성을 분리하여 설계할 수 있습니다.

 

 

 

의존관계 역전 원칙 (Dependency Inversion Principle, DIP)

의존 관계는 추상에 의존해야 하며, 구체화에는 의존하지 않아야 합니다.

포켓몬 클래스는 구체적인 구현이 아닌 추상화된 인터페이스나 추상 클래스에 의존해야 합니다.

예를 들어, 포켓몬 클래스가 공격 기능을 필요로 할 때, 포켓몬 클래스는 공격 인터페이스에 의존해야 합니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2023.06.19 - [Java] - 클래스 선언 및 생성자

 

클래스 선언 및 생성자

1. 클래스 선언 1) 클래스 선언의 개념 객체를 생성하기 위한 템플릿 또는 설계도 역할을 합니다. 클래스는 속성(attribute)과 메서드(method)로 구성되어 있으며, 객체의 상태와 동작을 정의하는데 사

devwarriorjungi.tistory.com

 

'Java' 카테고리의 다른 글

[Java] 메소드 선언 Method Declaration  (0) 2023.07.11
[Java] List 리스트의 개념과 종류  (0) 2023.07.03
[Java] 클래스 선언 및 생성자  (0) 2023.06.19
[Java] 변수 타입 변환  (0) 2023.06.19
[Java] 변수 선언과 접근제한  (0) 2023.06.17
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.