정리란 건 참 어려운 것 같다...
책은 거의 다 읽어 가고 또 실습도 하고 정리를 위해 책을 여러 번 이리 저리 보게 되는 건 좋은데
그럴 때 마다 어디를 덜어내야 하나. 어떻게 작성해야 하나 고민이 많은 것 같다.
더 많은 편이 있는데 총 9가지를 3번에 나누어 언급하고
SOLID는 양이 많더라도 한 번에 다 몰아서 업로드를 할 것 같다.
그럼 캡슐화, 상속, 다형성에 대해서 알아 보자!
필수개념.
실제 답변은 아래와 같은 틀로
캡슐화는 객체지향 프로그래밍의 핵심 개념 중 하나
입니다. 캡슐화는 주로 코드와 데이터를 하나의 작업 단위인 클래스로 결합하고 외부 코드가 이 데이터에 직접 접근학지 못하게 하는 방어막 역할을 합니다. 또한 객체 상태를 외부로부터 숨기고 이 상태에 접근하기 위한 일련의 public 메서드를 노출하는 기법
입니다. 각 객체가 클래스 안에서 상태를 private으로 유지할 때 캡슐화가 성립
되었다고 말할 수 있습니다. 따라서 캡슐화는 정보 은닉 메커니즘
이라고 불리기도 합니다. 캡슐화를 이용하는 코드는 몇 가지 장점이 있습니다.
먼저, 느슨한 결합이 가능
합니다. 예를 들어 클라이언트 코드와 어긋나지 않는 상태에서 클래스 변수의 이름을 변경할 수 있습니다. 또한 재사용성 할 수 있으며
클래스 내에서 데이터가 어떻게 조작되는지 클라이언트가 인식하지 못하므로 안전합니다. 마지막으로 필드를 테스트하는 것보다 메서드를 테스트하는 편이 더 쉽기 때문에 캡슐화를 이용한 코드는 테스트하기 쉽다는 장점
이 있습니다. 자바에서 캡슐화는 public, private, protected와 같은 접근 제어자로 구현
할 수 있습니다. 일반적으로 객체가 자체 상태를 관리할 때 상태는 private 변수로 선언되고public 메서드로 접근 및 수정됩니다. 예를 살펴 볼까요? Cat 클래스는 mood(기분), hungry(배고픔),energy(에너지)와 같은 필드로 구성할 수 있스비다. Cat 클래스의 외부 코드는 이러한 필드를 직접 수정할 수는 없지만, play, feed, sleep과 같이 클래스 상태를 내부적으로 수정하는 public 메서드를 호출할 수 있습니다. Cat 클래스는 meow와 같이 클래스 외부에서 접근할 수 없는 private 메서드도 가질 수 있습니다. 이것이 캡슐화 입니다.
추가적인 설명이 필요하면 아래와 같이 코드를 작성할 수 있으며 이를 작성할 때도 계속 설명을 이어 나가야 하며 아래와 같은 플로우를 따르자.
public class Cat {
private int mood = 50;
private int hungry = 50;
private int energy = 50;
public void sleep() {
System.out.println("Sleep ...");
energy++;
hungry++;
}
public void play() {
System.out.println("Play ...");
mood++;
energy--;
meow();
}
public void feed() {
System.out.println("Feed ...");
hungry--;
mood++;
meow();
}
private void meow() {
System.out.println("Meow!");
}
public int getMood() {
return mood;
}
public int getHungry() {
return hungry;
}
public int getEnergy() {
return energy;
}
}
상태는 public 메서드인 play, feed, sleep으로만 수정할 수 있으며 다음 코드에서 예를 볼 수 있습니다.
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.feed();
cat.play();
cat.feed();
cat.sleep();
System.out.println("Energy: " + cat.getEnergy());
System.out.println("Mood: " + cat.getMood());
System.out.println("Hungry: " + cat.getHungry());
}
}
출력 결과는 다음과 같습니다.
Feed ...
Meow!
Play ...
Meow!
Feed ...
Meow!
Sleep ...
Energy: 50
Mood: 53
Hungry: 49
필수개념.
실제 답변은 아래와 같은 틀로
상속은 객체지향 프로그래밍의 핵심 개념 중 하나
입니다. 상속을 통해
다른 객체를 기반으로 객체를 만들 수 있습니다.
상속은 다른 객체가 상당히 유사하고 몇 가지 공통된 로직을 공유하지만 완전히 동일하지는 않을 때 유용합니다. 상속은 객체가 다른 객체의 코드를 재사용할 수 있도록 허용하여 코드의 재사용성을 유지하고 각 객체만의 로직도 추가할 수 있습니다.
따라서 상속을 구현하려면 공통된 로직을 재사용하고 다른 클래스의 고유 로직을 추출해야 합니다. 이를 IS-A 관계라고 하며 부모-자녀 관계
라고도 합니다. 상속 관계는 Foo 가 Buzz를 상속할 때 ‘Foo IS-A Buzz’ 와 같이 표현할 수 있습니다. 예를 들어 ‘고양이 IS-A 고양이과의 동물’ 또는 ‘기차 IS-A 교통 수단’과 같이 상속 관계를 표현할 수 있습니다. IS-A 관계는 클래스의 계층 정의에 사용하는 작업 단위입니다. 자바에서 상속은 extends 키워드로 부모 클래스로부터 자식 클래스를 파생시켜 구현
합니다. 자식 클래스는 부모의 필드와 메서드를 재사용할 수 있으며 자신만의 필드와 메서드를 추가할 수 있습니다. 상속된 객체는 슈퍼클래스 또는 부모 클래스라고 하고 슈퍼클래스를 상속받은 객체는 서브클래스 또는 자식 클래스라고 합니다. 자바에서는 여러 개의 클래스를 상속할 수 없습니다.
따라서 서브클래스 또는 자식 클래스는 2개 이상의 슈퍼클래스 또는 부모 클래스로부터 필드와 메서드를 상속받을 수 없습니다. 예를 들어 employee(직원) 클래스는 부모 클래스로서 소프트웨어 회사의 모든 직원의 공통 로직을 정의할 수 있고, Programmer(개발자) 클래스는 자식 클래스로서 Employee 클래스를 상속받아 정의된 공통 로직을 사용하고 개발자에게 특화된 로직을추가할 수 있습니다. 다른 클래스도 Programmer나 Employee 클래슬르 상속할 수 있습니다.
추가적인 설명이 필요하면 아래와 같이 코드를 작성할 수 있으며 이를 작성할 때도 계속 설명을 이어 나가야 하며 아래와 같은 플로우를 따르자.
Employee 클래스는 꽤 간단합니다. 이 클래스는 직원의 이름을 포함합니다.
public class Employee {
private String name;
public Employee(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Programmer 클래스는 Employee를 상속받습니다. 직원 중 개발자의 이름을 포함합니다. 단, 개발자의 경우 속한 팀 이름도 있습니다.
public class Programmer extends Employee {
private String team;
public Programmer(String name, String team) {
super(name);
this.team = team;
}
public String getTeam() {
return team;
}
public void setTeam(String team) {
this.team = team;
}
}
그럼 이제 Programmer 인스턴스를 생성하고 Employee 클래스에서 상속받은 getName 메서드와 Programmer 클래스에서 상속받은 getTeam 메서드를 호출항려 상속을 테스트 해보곘습니다.
public class Main {
public static void main(String[] args) {
Programmer p = new Programmer("김수한무", "거북이와 두루미");
String name = p.getName();
String team = p.getTeam();
System.out.println(name + " is assigned to the " + team + " team");
}
}
출력 결과는 아래와 같습니다.
이번에는 다형성이다. 첫 도입부에서 썼던 내용의 반복이지만 예시 등이 추가되었다 :)
필수개념.
실제 답변은 아래와 같은 틀로
다형성은 객체지향 프로그래밍의 핵심 개념 중 하나입니다.
다형성을 뜻하는 ‘polymor-phism’은 ‘많다’를 의미하는 ‘poly’와 ‘형태’를 의미하는 ‘morph’라는 2개의 그리스어로 구성된 단어입니다. 즉 다형성은 많은 형태를 의미합니다.
좀 더 정확하게 말해, 객체지향 프로그래밍에서 다형성은 객체가 때에 따라 다르게 동작
할 수 있게 해주거나 어떤 동작이 다른 방법으로 동작할 수 있도록 하는 역할을 합니다. 다형성을 구현하는 방법 중 하나는 메서드 오버로딩
입니다. 여러 개의 메서드가 동일한 이름을 가지고 있지만 매개변수가 다른 경ㅇ우 컴파일러가 오버로드된 메서드 가운데 어떤 형식을 호출할 것인지 컴파일 시간에 식별할 수 있으므로 컴파일 타임 다형성이라고도 합니다.
이때 오버로드된 메서드의 형태에 따라 객체는 다르게 동작합니다. 예를 들어 Triangle(삼각형)이라는 클래스에는 서로 다른 매개벼수를 가진 여러 개의 draw 메서드를 정의할 수 있습니다. 다형성을 구현하는 또 다른 방법은 메서드 오버라이딩입니다. 메서드 오버라이등은 IS-A 관계가 잇을 때 일반적으로 사용하는 방법이며, 런타임 다형성 또는 동적 메서드 디스패치(dynamic method dispatch)
라고 합니다. 보통 여러 가지 메서드를 포함하는 인터페이스 구현으로 시작하며, 각 클래스는 특화된 동작을 수행하기 위해 인터페이스에 있는 메서드를 오버라이드 합니다. 이때 다형성이 타입에 대한 혼란 없이 이 클래스들을 부모 인터페이스와 똑같이 사용할 수 있게 합니다. 런타임에 자바가 이러한 클래스를 구별할 수 있고 어느 클래스가 사용되는지 알고 잇기 때문에 가능한 일입니다. 예를 들어 draw 메서드를 가지는 Shape(모양 이라는 인터페이스가 있다고 할 때, Triabngle,Rectangle(직사각형),Circle(원) 클래스가 Shape 인터페이스 구현에 있는 draw 메서드를 오버라이드해서 각 도형에 해당하는 모양을 그릴 수 있습니다.
추가적인 설명이 필요하면 아래와 같이 코드를 작성할 수 있으며 이를 작성할 때도 계속 설명을 이어 나가야 하며 아래와 같은 플로우를 따르자.
Triangle 클래스는 다음과 같이 세 가지 draw 메서드를 포함합니다.
public class Triangle {
public void draw() {
System.out.println("Draw default triangle ...");
}
public void draw(String color) {
System.out.println("Draw a triangle of color " + color);
}
public void draw(int size, String color) {
System.out.println("Draw a triangle of color " + color + " and scale it up with the new size of " + size);
}
}
다음으로 각 draw 메서드를 어떻게 호출할 수 있는지 보겠습니다.
public class Main {
public static void main(String[] args) {
Triangle triangle = new Triangle();
triangle.draw();
triangle.draw("red");
triangle.draw(10, "blue");
}
}
출력 결과는 아래와 같습니다.
Draw default triangle ...
Draw a triangle of color red
Draw a triangle of color blue and scale it up with the new size of 10
이번에는 런타임 다형성을 구현하는 예제를 살펴 보겠습니다. draw 메서드를 다음과 같이 인터페이스에 선언합니다.
public interface Shape {
public void draw();
}
Triangle, Rectangle, Circle 클래스는 Shape 인터페이스를 구현하고 해당하는 모양을 그리도록 draw 메서드를 오버라이드합니다.
public class Triangle implements Shape {
@Override
public void draw() {
System.out.println("Draw a triangle ...");
}
}
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Draw a rectangle ...");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Draw a circle ...");
}
}
이제 삼각형, 직사각형, 원의 각 클래스에 대한 인스턴스를 생성하고 draw 메서드를 호출하겠습니다.
public class Main {
public static void main(String[] args) {
Shape triangle = new Triangle();
Shape rectangle = new Rectangle();
Shape circle = new Circle();
triangle.draw();
rectangle.draw();
circle.draw();
}
}
출력 결과를 보면 런타임에 자바가 적합한 draw 메서드를 호출했다는 것을 알 수 있습니다.
글 잘 봤습니다.