객체지향 프로그래밍

[자바 JAVA] 객채지향 - 클래스(Class) 와 객체(Object)

codificacion 2023. 5. 18. 17:10

** 학습 자료 개인 학습용으로 작성한 내용이니 정확하지 않을 수 있음 ** 

TODAY I LEARNED:

1. 객체지향 프로그램이 무엇이며

2. 클래스와 객채

3. 필드와 메서드 (Static 변수와 Instance 변수, 메서드 오버라이딩)

4. 생성자 (this vs this()

5. 내부 클래스 (내부, 멤버, 지역내부 클래스)


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

객체 지향 프로그래밍은 컴퓨터 언어의 하나이며 프로그래밍에 필요한 객체(object) 또는 데이터의 모임으로 추상화시켜

이릍 통해 프로그래밍을 하는 것임.

객체 지향 프로그래밍은 Java C++ C 파이썬 등에서 사용 됨.

 

영문 설명: OOP stands for Object-Oriented Programming. <https://www.w3schools.com/java/java_oop.asp>

Procedural programming is about writing procedures or methods that perform operations on the data, while object-oriented programming is about creating objects that contain both data and methods.

 

객체지향 프로그램 장점: 

- 빠르고 실행하기 쉬움

- 명확한 구조

- 코드 간결하고 깨끗하게 유지 가능

- 코드 재사용이 가능함

 

객체지향을 구조와 작성벙법을 알기 위해 하기 개념에 대해 알아야 함:

- 클래스(class) 와 객체(object)

    - 필드(field), 메서드(method), 생성자(constructor), 내부클래스(inner class)

- 인스턴스(instance)

- 상속(inheritance)

- 캡슐화(encapsulation)

- 다향성(polymorphism)

- 추상화(abstraction)

 

지금부터 위 내용을 하나하나 살펴 볼 예정임.


2. 클래스(class) 와 객체(object)

클래스란 객체를 정의한 또는 설계라고 함.

객체란 실생활에서 우리가 인식할 수 있는 사물임. 실재하는 모든 것이자 사용할 수 이는 실체라고도 함. 

따라서 클래스와 객체는 항상 같이 사용 됨. 

클래스는 객체의 상태를 나타내는 필드(field)와 객체의 행동을 나타내는 메소드(method) 그리고 생성자로 구성됨.

필드(field)는 클래스에 포함된 변수(variable)를 의미함.

메소드(method)란 어떠한 특정 작업을 수행하기 위한 명령문의 집합이라 함.

 

예시) 집을 만든다고 가정하자

1. 클래스: 집의 설계도

2. 객체: 생성된 집 (결과물)

    - 필드: 집의 속성을 나타냄 (집 외벽 색상, 인터리어 디자인 등)

    - 메서드: 집의 기능을 나타냄 (수도, 전기, 스마트홈 등)

3. 인스턴스: 설계도에 따른 여러 집(객체)들이 만들어짐 (객체를 만드는 과정 = 인스턴스화(instantiate))

 

예시2) 붕어빵 기계로 클래스, 객체, 인스턴스를 이해하자:

붕어빵 만드는 과정은 인스턴스화이며 인스턴스화 통해 만들어지는 인스턴스이며 그것이 객체이다.

객체는 모든 인스턴스를 포괄하는 넓은 의미를 가지고 있고 인스턴스는 해당 객체가 어떤 클래스로부터 생성된 것인지를 강조함.

 

클래스 작성 방법:

class 클래스명 { // 클래스 정의
// 반드시 첫문자는 대문자로 시작하고 
//단어가 2개 이상일 경우 각 단어의 첫 번째 문자를 대문자로 표현함
}
public class ExampleClass {
	int x = 10; // (1)필드
	void printX() {...} // (2)메서드
	ExampleClass {...} // (3)생성자
	class ExampleClass2 {...} // (4)이너 클래스
} 

 

클래스의 구성요소: 필드(field), 메서드(method), 생성자(constructor), 내부클래스(inner class)

   - 필드:  클래스의 속성을 나타내는 변수 ex) 자동차에 모델명, 컬러, 오일타입 등

   - 메소드: 클래스의 기능을 나타내는 함수 ex) 자동차 시동하기, 가속하기, 정지하기 등

   - 생성자: 클래스의 객체를 생성하는 역할

   - 이너 클래스: 클래스 내부의 클래스

 

객체의 구성요소: 필드(속성)과 기능(메서드)으로 구성되어 있고 하나의 객체에는 다양한 속성과 기능 집합으로 이루어져 있음. 

 

예시) 자동차 (필드와 메서드를 더 쉽게 이해하기)

1. 필드(속성): 모델, 바퀴의 개수, 문의 개수, 컬러 등

2. 메서드(기능): 시동 걸기, 가속하기, 정지하기 등

 

객체 생성할때는 "new" 키워드로 생성 가능하며 "."로 객체의 멤버에 접근이 가능하다.

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

	Car bmw = new Car(); // Car 클래스를 기반으로 생성된 bmw 인스턴스
	Car tesla = new Car(); // Car 클래스를 기반으로 생성된 tesla 인스턴스
	Car audi = new Car(); // Car 클래스를 기반으로 생성된 audi 인스턴스
}

// 클래스명 참조_변수명 = new 생성자();

** 참조변수는 실제 데이터 값을 저장하는 것이 아니라 실제 데이터가 위치해 있는 힘 메모리의 주소를 저장하는 변수를 의미한다 **

 

public class CarTest {
    public static void main(String[] args) {
        Car tesla = new Car("Model 3", "빨강"); // 객체 생성. 

        System.out.println("내 차의 모델은 " + tesla.model + "이고 " + "색은 " + tesla.color + "입니다."); // 필드 호출
        tesla.power(); // 메서드 호출
        tesla.accelerate();
        tesla.stop();
    }
}

class Car {
    public String model; // 필드 선언
    public String color;

    public Car(String model, String color) { // 인스턴스 초기화를 위한 생성자 함수. 이후 챕터에서 학습 예정.
        this.model = model;
        this.color = color;
    }

    void power() { // 메서드 선언
        System.out.println("시동을 걸었습니다.");
    }

    void accelerate() {
        System.out.println("더 빠르게!");
    }

    void stop(){
        System.out.println("멈춰!!");
    }
}

// 출력값
내 차의 모델은 Model 3이고 색은 빨강입니다.
시동을 걸었습니다.
더 빠르게!
멈춰!!

3. 필드와 메서드 (Static 변수와 Instance 변수, 메서드 오버라이딩)

자바에서는 변수는 크게 클래스 변수, 인스턴스 변수, 지역 변수로 구분 된다. 

필드는 클래스 변수와 인스턴스 변수이고 "static" 키워드의 유무로 구분이 가능하다.
메서드 내에 포함된 모든 변수를 지역 변수라고 부른다. 

 

1. 클래스 변수: 클래스에 속하는 변수이며 해당 클래스의 모든 인스턴스들이 공유하는 변수이다.

클래스 변수는 "static"⭐ 키워드를 통해 선언이 되고, 클래스의 어떤 인스턴스에서도 접근 가능하다.

프로그램이 실행되는 동안 메모리에 유지되며, 일반적으로 상수나 공통된 속성을 나타내는 데 사용된다.

public class MyClass {
    static int count; // 클래스 변수 선언
}

2. 인스턴스 변수: 인스턴스 변수는 클래스의 객체마다 개별적으로 유지되는 변수이며 객체의 상태를 나타내는 데 사용된다. 클래스 내부의 메서드에서 접근할 수 있으며, 클래스 외부에서는 객체를 통해 접근이 가능하다.

인스턴스 변수는 객체가 생성될 때마다 메모리에 할당되고, 객체가 소멸될 때까지 유지된다.

public class MyClass {
    int age; // 인스턴스 변수 선언
}

3. 지역 변수: 지역 변수는 메서드, 생성자, 블록 내에서 선언되는 변수로서 해당 블록 내에서만 접근할 수 있다.

메서드가 호출될 때 생성되고, 메서드 실행이 완료되면 소멸된다

public class MyClass {
    void myMethod() {
        int number; // 지역 변수 선언
    }
}

Summary:

클래스 변수는 클래스에 속하며 모든 인스턴스에서 공유되는 변수이다.

인스턴스 변수는 객체마다 개별적으로 유지되는 변수이며, 객체의 상태를 나타낸다.

지역 변수는 블록 내에서만 접근 가능한 변수로서, 메서드나 생성자 내에서 사용된.

 

4. ⭐"Static"

Static = 정적

Static 키워드가 뭍은 멤버를 "Static member" (정적 멤버)라고 불린다.

정적 메서드: static 키워드를 사용하여 선언된 메서드는 정적 메서드로써

해당 클래스의 인스턴스를 생성하지 않고도 호출할 수 있는 메서드이다.

 

5. 메서드: 이전 설명과 같이 차로 예시를 들면 메서드는 기능을 말한다. 

차가 시동을 건다, 브레이크를 밟는다, 가속한다 등.

메서드는 메서드 시그니처와 바디로 나뉜다. 

public static int add(int x, int y) { // 메서드 시그니처
	int result = x + y; // 메서드 바디
	return result;
}

메서드를 호출하는 방법:

메서드는 클래스 멤버이기 때문에 클래스 외부에서 메서드를 사용 하기 위해 우선 인스턴스를 생성해야 한다. 

이는 "." 포인트 연산자를 통해 메서드 호출이 가능하다.

MyClass obj = new MyClass();  // MyClass 객체 생성
obj.myMethod();  // 인스턴스 메서드 호출

메서드 오버로딩:

메서드 오버로딩이란 하나의 클래스에 같은 이름의 메서드를 여러개 정의 하는 것이다. 

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
    
    public double add(double a, double b) {
        return a + b;
    }
}

첫 번째 add 메서드는 int 타입의 매개변수를 받고, 두 개의 정수를 더한 결과를 반환한다.

두 번째 add 메서드는 double 타입의 매개변수를 받고, 두 개의 실수를 더한 결과를 반환한다.

이렇게 매개변수의 타입이 다르므로 같은 이름의 메서드를 여러 개 정의할 수 있는 것이 메서드 오버로딩이다.

하지만 왜 메서드 오버로딩을 사용할까? 하나의 메서드로 여러 경우의 수를 해결 할 수 있기 때문이다.

4. 생성자 (this vs this())

생성자: 객체의 생성 역할을 하는 클래스의 구성 요소이며 "new"키워드를 사용하여 생성이 된다.

생성자는 인스턴스 변수들을 초기화하는 데 사용되는 메서드이다. 

생성자의 이름은 반드시 클래스의 이름과 같아야 하고 return 타입이 없다. 

public class Student {
    private String name;

    // 생성자
    public Student(String name) {
        this.name = name;
    }

    // 메서드
    public void introduce() {
        System.out.println("My name is " + name + ".");
    }
}

public class Main {
    public static void main(String[] args) {
        Student student1 = new Student("John");
        student1.introduce();  // 출력: My name is John.

        Student student2 = new Student("Emily");
        student2.introduce();  // 출력: My name is Emily.
    }
}

객체의 생성자와 인스턴스 메서드에서 사용하는 키워드는 바로 this와 this() 이다. 

this:

this 는 현재 객체를 가르키는 참조이다. 주로 인스턴스 변수와 메서드를 구분하기 위해 사용 된다. 

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;  // 인스턴스 변수에 전달된 값을 할당하기 위해 this 키워드 사용
    }

    public void printName() {
        System.out.println("My name is " + this.name);  // 인스턴스 변수에 접근하기 위해 this 키워드 사용
    }
}

this():

this()는 같은 클래스의 다른 생성자를 호출할때 사용 된다. 

public class Test {
    public static void main(String[] args) {
        Example example = new Example();
        Example example2 = new Example(5);
    }
}

class Example  {
    public Example() {
        System.out.println("Example의 기본 생성자 호출!");
    };

    public Example(int x) {
        this();
        System.out.println("Example의 두 번째 생성자 호출!");
    }
}

//Output
Example의 기본 생성자 호출!
Example의 기본 생성자 호출!
Example의 두 번째 생성자 호출!

5. 내부 클래스 (내부, 멤버, 지역내부 클래스)

class Outer { // 외부 클래스
	
	class Inner {
		// 인스턴스 내부 클래스	
	}
	
	static class StaticInner {
		// 정적 내부 클래스
	}

	void run() {
		class LocalInner {
		// 지역 내부 클래스
		}
	}
}

내부 클래스:

다른 클래스 내에 정의되는 클래스를 말한다.

내부 클래스는 외부 클래스의 멤버로 간주되며, 외부 클래스의 멤버에 접근할 수 있다.

 

내부 클래스에는 멤버 내부 클래스, 지역 내부 클래스가 있다.

1. 멤버 내부 클래스: 외부 클래스의 멤버로서 선언되는 내부 클래스이다.

외부 클래스의 인스턴스를 생성해야만 멤버 내부 클래스의 인스턴스를 생성할 수 있다.

멤버 내부 클래스는 외부 클래스의 필드, 메서드에 접근할 수 있으며, 외부 클래스의 멤버와 같은 접근 제어를 가질 수 있다.

2. 지역 내부 클래스: 메서드나 블록 내에 선언되는 내부 클래스이다.

지역 내부 클래스는 선언된 메서드나 블록 내에서만 유효하며, 외부에서 직접 접근할 수 없다.

주로 메서드 내에서 복잡한 로직을 구현하거나 특정 조건에 따라 다르게 동작해야 할 때 사용된다.