OOP 란 객체 지향 프로그래밍(Object-Oriented Programming)을 줄여서 흔히들 OOP라고 부른다.
OOP란 현실 세계를 프로그램 설계에 반영한다는 개념을 기반으로 접근하는 방법이다. OOP는 90년대 초반부터 유명해지기 시작했지만 전 세계의 많은 개발자들이 사용하고 있는 설계 패턴 중 하나이다.
데이와 데이터를 활용하는 함수를 캡슐(class) 혹은 컨테이너에 넣는것을 이야기한다.
캡슐화를 하는 가장 큰 이유는 정보은닉에 있다.
캡슐화를 통해 외부에서 내부의 정보에 접근하거나 변경할 수 없게 직접적인 접근을 막고 객체가 제공하는 필드와 메소드를 통해서 접근이 가능하다.
이렇게 접근을 제한함으로써 유지보수나 확장 시 오류의 범위를 최소화할 수 있고 객체 내의 정보 손상과 오용을 방지하고 데이터가 변경되어도 다른 객체에 영향을 주지않아 독립성이 좋다.
아니 근데 독립적인게 장점인건 class의 장점이지 캡슐화의 장점은 아니지 않나?
예제)
package encapsualtion;
public class BeforeEncapsualtion {
public static void main(String[] args) {
Calculator c = new Calculator();
c.num1 = 20;
c.num2 = 30;
c.sum();
//여기까지는 문제가 없을 수도 있다. 하지만 사용자가 sum 의 접근이 가능하다면 ?
c.sum = 20;
//사용자가 마음대로 필드에 접근하여 값을 수정할 수 있음. 즉, 원하지 않는 결과를 얻어낼 수 있다.
System.out.println(c.sum);
}
}
class Calculator{
public int num1;
public int num2;
public int sum;
public void sum() {
this.sum = this.num1 + this.num2;
}
};
(출처 : https://sujl95.tistory.com/32)
상속은 무언가로부터 물려 받다는 개념이다. 현실 세계에서 부모의 재산을 자식이 물려받는것과 비슷하다.
객체 지향에서의 상속은 inheritance(상속)이 아닌 extends(재사용과 확장)으로 이해하는것이 좋다.
- 클래스가 상속을 위해 특별히 설계되었거나 구조화가 잘 된 클래스를 확장의 목적으로 상속하는것이 안전하다.
- 동일 개발자가 하위 클래스와 상위 클래스의 통제하는 경우 같은 패키지내에서 상속하는 것이 안전하다.
위 사진은 현실세계의 상속이다 하지만 객체지향에서의 상속은 이와 조금 다르다.
위 관계는 상속의 관계가 아니다. 동물은 포유류와 조류의 부모가 아니며 고래 또한 부모가 포유류가 될수는 없다.
예제)
공통의 속성이나 기능을 묶어 이름을 붙이는 것
객체 지향적 관점에서 클래스를 정의하는 것을 바로 추상화라고 정의 내릴 수 있다.
예시를 들자면 영재, 유리, 유미, 장민, 명래 라는 객체를 하나로 묶으려고 할때 사람 또는 포유류 라고 묶는것을 추상화 라고한다.
C++의 아버지는 추상화를 "구현 세부 정보를 숨기는 일반 인터페이스를 지정하는 행위" 라고 정의했다.
뭔 개소리야
4.다형성(Polymorphism)
다형성(polymorphism)이란 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미합니다.
자바에서는 이러한 다형성을 부모 클래스 타입의 참조 변수로 자식 클래스 타입의 인스턴스를 참조할 수 있도록 하여 구현하고 있습니다.
다형성은 상속, 추상화, 캡슐화와 더불어 객체 지향 프로그래밍을 구성하는 중요한 특징 중 하나입니다.
예제1)
package encapsualtion;
public class BeforeEncapsualtion {
public static void main(String[] args) {
Youngjae j = new Youngjae();
Company c = new Company();
c.pass(j);
}
}
class Human{
private String language;
public Human() {
super();
}
public Human(String language) {
super();
this.language = language;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String hello(){
return "hello";
}
};
class Company{
public void pass(Human m) {
if(m instanceof Myeongrae) {
System.out.println("명래님 합격이에요 ! ");
}else {
System.out.println("영재님 합격이에요 ! ");
}
}
}
class Myeongrae extends Human{
}
class Youngjae extends Human{
}
별 문제없어보이는 코드지만 Human 을 상속하는 class 가 많아질수록 if 문을 추가해야하기 때문에 좋지않다 다음처럼 pass 인터페이스를 작성하고 인터페이스를 구현하도록 변경해보자.
package encapsualtion;
public class BeforeEncapsualtion {
public static void main(String[] args) {
Youngjae j = new Youngjae();
Company c = new Company();
c.pass(j);
}
}
interface Passable{
void pass();
}
class Human{
private String language;
public Human() {
super();
}
public Human(String language) {
super();
this.language = language;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String hello(){
return "hello";
}
};
class Company{
public void pass(Passable p) {
p.pass();
}
}
class Myeongrae extends Human implements Passable{
public void pass() {
System.out.println("명래님 합격이에요 ! ");
}
}
class Youngjae extends Human implements Passable{
public void pass() {
System.out.println("영재님 합격이에요 !");
}
}
이렇게 되면 human 을 상속받는 class 가 늘어나더라도 pass method의 수정을 하지않아도 된다.
이렇게 하나의 객체가 여러개의 자료형을 가질 수 있는것을 객체지향에서 다형성 이라고 한다.
즉 Youngjae class 의 객체는 다음과 같이 표현될 수 있다.
Youngjae j = new Youngjae();
Human a = new Youngjae();
Passable b = new Youngjae();