오늘은 객체 지향 언어의 특성에 대해 공부하였는데, 여태 대학에 다니며 아무리 들어도 이해가 가지 않았던 객체에 대한 개념을 각잡고 한번 다시 공부해보는 시간을 가졌다.

또한 내가 직접 코드를 치면서 공부하니 조금은 감이 잡히는 것 같기도..?

아직 끝난건 아니지만 현재까지 공부한 것을 토대로 정리해보고자 한다.

객체지향 언어(Object-Oriented Programming, OOP)의 특성

 

1. 캡슐화(Encapsulation)

캡슐화란 객체를 캡슐로 싸서 내부를 보호 하고 볼 수 없게 하는 것으로 객체의 본질적인 특성이다.

ex) 캡슐알약을 생각하면 쉬운데, 캡슐 안에 든 약이 어떤 색인지. 어떤 성분인지 보이지 않고 외부의 접근으로 부터 안전함.

객체는 기본적으로 캡슐화를 원칙으로 하지만, 외부와의 연결을 위하여 몇 부분 정도를 공개 노출한다.

ex) TV는 전자회로를 케이스 안에 숨기고(캡슐화), 전원버튼이나 리모콘 작동을 위한 통신 단자 부분은 노출시킨다.

실세계와는 다르게, 자바는 클래스(class) 라는 캡슐을 사용하고 필드(멤버 변수) 메소드 (멤버 함수) 로 구성된다.

아래 코드는 쉽게 이해하고자 내가 작성한 간단한 예제이다.

class Animal{
    String name; // 필드(멤버 변수)
    int age; // 필드(멤버 변수)
    void eat(){
        System.out.println("저는 육식이 좋아요");
    }; // 메소드(멤버 함수)
}

public class Main{
    public static void main(String[] args){

        Animal myAnimal = new Animal();

        myAnimal.name = "호랑이";
        myAnimal.age = 11;

        System.out.println("저는 "+ myAnimal.name + "입니다");
        System.out.println("저는 " + myAnimal.age + "살 입니다");
        myAnimal.eat();

    }
}

위 코드는 내가 쉽게 이해하기 위해 작성해본 코드이다. 

결론적으로 우리는 위의 내용만으로 "아! 호랑이라는 객체를 만들기 위해 Animal 이라는 클래스를 사용했구나" 라고 이해해도 되고, 같은 맥락으로 "아! Animal 이라는 클래스를 만들어 호랑이 라는 객체를 만들었구나" 라고 생각해도 될 듯 싶다

그런데 어디서 많이 본 형태가 있지 않은가?

ㅅ..스캐너 ..?

위 코드와 비슷하게 우리가 평소에 코딩테스트를 좀 준비했다면 바로 보이는 구조일텐데

Scanner sc  = new Scanner(System.in)

라는 구조와 유사하다는것을 한눈에 확인 할  수 있다. 여기서 내가 생각한건 '객체를 생성하는 과정은 같으니까 Scanner 도 어딘가에 클래스가 정의가 되어 있겠지?' 라고 생각했다

우리가 Scanner 을 사용하기 위해서는 늘 import java.util.Scanner; 를 임포트하는데,

이미 여기서 우리의 친절하고 고마운 개발자 대선배 님들께서 표준 라이브러리로 작성해놓으신 클래스가 존재하기 때문에, 우리는 이를 가져다 쓰기만 하면 된다...(감사합니다.. 감사합니다..).

우리가 만약 위에서 Animal 처럼 자료구조와 알고리즘을 모두 구현하여 작성하려고 했다면 코딩할때마다 얼마나 골이 아프겠는가..

 

2. 상속(Inheritance)

두번째 개념은 상속인데,

상속이란 상위 개채(슈퍼 클래스, 상위 클래스) 의 속성을 하위 개채(서브 클래스, 하위 클래스) 에 물려줌으로써 코드 재사용성을 높이고 그에 따라 개발 시간을 단축시킨다.

이때, 슈퍼클래스의 속성을 그대로 물려받아 사용이 가능하고, 필요한 속성을 추가하여 사용할 수 도 있다.

이또한 위에 코드를 연장하여 작성했는데, 코드를 보면 더 이해하기가 쉬울 것 같다

class Animal{
    String name;
    int age;
    void eat(){
        System.out.println("저는 육식이 좋아요");
    };
}

class Dog extends Animal{ // 여기서 Dog 클래스가 Animal 클래스를 상속받음
    String name;
    void bark(){
        System.out.println("멍멍!");
    }
}

public class Main{
    public static void main(String[] args){

        Animal myAnimal = new Animal();
        Dog myDog = new Dog();

        myAnimal.name = "호랑이";
        myAnimal.age = 11;
        myDog.name = "강아지";

        System.out.println("저는 "+ myAnimal.name + "입니다");
        System.out.println("저는 " + myAnimal.age + "살 입니다");
        myAnimal.eat();
        System.out.println("저의 이름은 "+ myDog.name);
        myDog.bark();

	    }
}

 

3. 다형성(Polymorphism)

다형성이란 같은 이름의 메소드가 클래스 혹은 객체에 따라 다르게 동작하도록 구현되는 것을 말한다.

예를들어, 우리가 만들어 놓은 Animal이라는 클래스에 동물의 울음을 speak(){...} 라는 메소드로 구현 해놓았다고 가정하자.

이때 우리가 서브클래스로 만들어 놓은 Dog 클래스에서도 speak라는 메소드를 새로 사용하고 싶은데, 상속의 개념에 의하면, 이미 우리는 슈퍼 클래스에서 상속받은 대로만 사용해야한다고 생각할 것이다.

하지만 우리는 역시나 다들 불효자들이었을까, 부모님의 생각대로 하고 싶지 않다는 마음이 크기때문인지, 부모님이 알려주신 말씀(슈퍼 클래스, 부모 클래스) 대로 살지 않고 내 뜻(서브 클래스, 자식 클래스)대로 살아가기 위해 부모님의 말과 다르게 행동하는 것을 생각하면 쉬울 것 같다.

이렇게 슈퍼클래스에서 구현된 메소드를 서브 클래스가 입맛에 맞게 다시 구현하는 것을 메소드 오버라이딩 이라고 부른다.

이것도 위의 코드를 연장하여 한번 알아보자

class Animal{
    String name;
    int age;
    void eat(){
        System.out.println("저는 육식이 좋아요");
    };
    void speak(){
        System.out.println("SIUUUU"); // 기존 메소드는 이렇게 구현
    }
}

class Dog extends Animal{
    String name;
    void bark(){
        System.out.println("멍멍!");
    }
    void speak(){
        System.out.println("죄송하지만, 저는 호동생이 아닙니다"); // 여기서 메소드 오버라이딩
    }
}

public class Main{
    public static void main(String[] args){

        Animal myAnimal = new Animal();
        Dog myDog = new Dog();

        myAnimal.name = "호랑이";
        myAnimal.age = 11;
        myDog.name = "강아지";

        System.out.println("저는 "+ myAnimal.name + "입니다");
        System.out.println("저는 " + myAnimal.age + "살 입니다");
        myAnimal.eat();
        System.out.println("저의 이름은 "+ myDog.name);
        myDog.bark();
        myAnimal.speak();
        myDog.speak();

    }
}

위 코드처럼 "SIUUUU" 를 출력하라고 Animal 클래스에서 speak() 메소드를 지정해놓았지만,

그것을 상속받는 Dog 클래스에서는 " 죄송하지만, 저는 호동생이 아닙니다" 로 새로 speak()를 바꾸어 (메소드 오버라이딩) 출력하는 결과를 볼 수 있다.

 

오늘 공부하면서 느낀거는.. 기본 문법도 당연하지만 이러한 어려운 개념도 코드를 쉽게나마 쳐보면 이해가 가긴 가는구나 생각이 들었다.. 비록 객체의 완전한 개념은 아니고 내가 지금까지 이해한대로 적은 거라 틀린 내용이 있을 수도 있지만, 앞으로 더 공부하고 알아가며 틀린 부분은 바로 잡도록 해야겠다

그럼 20000!