JAVA

[JAVA] 객체지향 언어란 무엇인가? - 객체, 인스턴스, 클래스, OOL특징

sagecode 2024. 11. 22. 21:23

우리가 프로그래밍 언어를 배울 때, 객체지향 언어라는 말을 많이 들어봤을 것이다. 그럼 대체 객체지향 언어는 무엇일까?

 

1. 객체

우선 객체에 대한 정의를 해야한다. 

  • 객체 : 현실세계에 존재하거나 추상적으로 생각하는 것 모든 것을 얘기한다.

  • 객체 모델링 : 현실 세계 객체의 속성과 동작을 추려내어 소프트웨어 객체의 필드와 메소드로 정의하는 과정이다.

2. 클래스

현실에서의 객체는 설계도를 바탕으로 만들어진다. 메모리에서 사용하고 싶은 객체가 있다면 설계도를 바탕으로 해당 객체를 만들어야 되는데 그 설계도를 JAVA에서는 클래스라고 한다.

  • 클래스(Class) : 객체를 생성하기 위한 설계도 역할을 하고, 프로그램에서 사용할 객체의 필드와 메소드가 정의 되어 있다.
  • 인스턴스(Instance) : 클래스로부터 만들어진 객체를 해당 클래스의 인스턴스라고 한다.
  • new 연산자 : 클래스로부터 객체를 생성시키는 연산자이다.
  • 클래스의 구성 멤버
    • 필드(Field) : 객체에 있는 속성, 이 객체를 이루는 것들을 말한다.
    • 생성자(Constructor) : 객체 생성 시 초기화 역할을 담당한다. 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 한다.
    • 메소드(Method) : 객체의 동작에 해당하는 중괄호 블록이다. 메소드를 호출하게 되면 중괄호 블록에 있는 모든 코드들이 일괄적으로 실행된다.

3. 객체 지향 언어의 특징

프로그램을 다수의 객체로 만든 다음, 이들끼리 서로 상호작용을 할 수 있도록 만든 언어가 객체 지향 언어다. 이 언어는 객체라는 개념을 쓰기 때문에 4가지 특징이 존재한다.

  • 캡슐화
    • 데이터와 코드의 형태를 외부로부터 알 수 없게 하고, 데이터와 구조의 역할, 기능을 하나의 캡슐 형태로 만드는 방법 (정보 은닉)
    • 캡슐화는 private라는 방법을 사용해서 접근을 제어하고, set/get 메소드를 사용해 데이터를 꺼내올 수 있는 장치를 만든다.
public class Persontest {
	public static void main(String[] args) {
    	Person p1 = new Person(10); // int 매개변수가 들어간 생성자 호출 불가
        System.out.println(p1.age); // p1 인스턴스 생성 안됨
        
        Person p2 = new Person(); // public 생성자 호출
        p2.setAge(10); // p2 인스턴스의 age값 설정
        System.out.println(p2.age); // p2 인스턴스의 age 직접 접근 불가
        System.out.println(p2.getAge()); // p2 인스턴스의 age값 호출
    }
}

class Person {
	private Person(int age) {
    	this.age = age;
    } // private 생성자
	
	public Person() {
		
	} // public 생성자
    
	private int age;
    
    public int getAge() {
    	return age;
    }
    
    public void setAge(int age) {
    	if (age >= 0) {
        	this.age = age;
        }
    }
}

이렇게 private 접근 제한을 통해 class내에서만 데이터를 사용할 수 있도록 할 수 있다.

  • 추상화
    • 어떤 대상 또는 집단의 공통적이고 본질적인 특징을 추출하여 정의한 것을 의미한다.
    • 왜 추상화를 사용할까? 
      • 중복 코드를 줄일 수 있다.
      • 유지보수, 가독성을 높일 수 있다. -> extends animal을 하게 되면서 Bird등의 class가 동물에 속하는지 알 수 있다.
      • 필드, 메소드 이름을 통일시킬 수 있다.
public abstract class Animal {
    private String type;
    private int legs;

    public Test(String type, int legs) {
        this.type = type;
        this.legs = legs;
    }

    abstract void howl();
    abstract void walk();
    
    public String getType() {
        return type;
    }
    
    public String getLegs() {
        return legs;
    }
}

public class Bird extends Animal {

	public Bird() {
    	super("새", 2);
	}

	@override
        void howl() {
            system.out.println("짹쨱");
        }
        void walk() {
            system.out.println("총총");
        }
}
    • 객체를 직접 생성할 수 있는 클래스를 실체 클래스, 그것들의 공통적인 특성을 추출해서 선언한 클래스를 추상 클래스라고 한다.
    • 추상 클래스를 선언할 때에는 abstract를 붙이고 클래스를 선언한다.
      • abstract를 붙이면 new 연산자를 이용해 객체 생성이 불가하며, 상속을 통해 자식클래스만 만들 수 있다.

 

  •  상속
    • 객체를 추상화 또는 구현할 때, 기존에 구현한 클래스를 재활용하여 구현할 수 있는 것을 의미한다.
    • 이 때, 재활용한 클래스는 상위 클래스, 새로 구현한 클래스는 하위 클래스가 된다.
    • 상속을 통해, 코드 재사용성을 높일 수 있다.
    • 상속을 할 때, 자식클래스를 선언할 때 부모 클래스를 extends 뒤에 기술한다. 
class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class Student extends Person { // Person : 부모 클래스, Student : 자식 클래스
    int grade;

    Student(String name, int age, int grade) { // 자식 클래스의 생성자 호출
        super(name, age); // 부모 클래스의 생성자 호출
        this.grade = grade;
    }
}
  • 다형성
    • 하나의 객체 또는 메소드가 여러가지 타입을 가질 수 있는것을 말한다.
    • 다른 표현으로는 같은 자료형에 여러가지 데이터를 대입하여 다양한 결과를 얻어낼 수 있는 성질을 말한다.
Class English() {
	String message = "Hello";
}

Class Korean() {
	String message = "안녕";
}

Class Chinese() {
	String message = "Ni Hao";
}

Class LanguageTranslator() {

// 오버로딩
    
    void speak(English english) {
        system.out.println(enlish.message);
    }
    void speak(Korean korean) {
    	system.out.println(korean.message);
    }
    void speak(Chinese chinese) {
    	system.out.println(chinese.message);
    }
}

public class Translator {
	public static void main(String[] args) {	
        English english = new English();
        Korean korean = new Korean();
        Chinese chinese = new Chinese();

        LanguageTranslator lt = new LanguageTranslator();

        lt.speak(english);      // Hello 출력
        lt.speak(korean);       // 안녕 출력
        lt.speak(chinese);       // Ni Hao 출력
	}
}
  • 이런식으로 같은 메소드를 다른 파라미터를 받아 다른 결과를 낼 수 있다. -> Overloading
  • Overloading? 하나의 클래스에 같은 이름의 함수를 정의하고, 매개 변수의 type과 개수를 다르게 하여, 사용할 수 있느 방법.
    • Overloading이 안되는 경우
      • return 값만 다른경우
      • 접근 제어자만 다른경우
    • 정적 다형성이라고 함.
  • Overriding? 상위 클래스가 가지고 있느 메소드를 하위 클래스가 재정의 하여 사용하는 방법.
    • Overriding이 안되는 경우
      • 자식 클래스에서 재정의하는 메소드의 접근 제어자는 부모 클래스에서 정의된 접근 제어자보다 좁게 정의할 수 없다.
      • 자식 클래스에서의 예외처리는 부모 클래스에서의 예외보다 더 넓게 정할 수 없다.
    • 동적 다형성이라고 함.
  • @Overriding, @Overloading 처럼 @를 쓰는 이유?
    • @는 annotation이라고 부르며 overriding, overloading이 사용되지 않았을 때, 컴파일 오류를 내어 검증하는 효과를 지닌다.