Language/Java

자바의 객체지향 정리

hu6r1s 2023. 12. 22. 17:46
클래스와 객체
클래스의 정의 : 클래스란 객체를 정의해 놓은 것이다.
클래스의 용도 : 클래스는 객체를 생성하는데 사용한다.
객체의 정의 : 실제로 존재하는 것, 사물 또는 개념
객체의 용도 : 객체가 가지고 있는 속성과 기능에 따라 다르다.

 

쉽게 표현하자면 이렇다.

클래스
객체
제품 설계도 제품
TV 설계도 TV
붕어빵 기계 붕어빵

객체와 인스턴스 용어 정리

  • 객체 : 모든 인스턴스를 대표하는 일반전인 용어
  • 인스턴스 : 특정 클래스로부터 생성된 객체
  • 인스턴스화 : 클래스 => 인스턴스

더 쉽게 정리되어진 을 찾아봤다.

객체의 구성요소

객체 = 속성(변수) + 기능(메서드)

객체의 생성

객체의 생성

클래스명 변수명;
- 클래스의 객체를 참조하기 위한 참조변수를 선언
변수명 = new 클래스명;
- 생성된 객체의 주소를 참조변수에 저장

객체 생성 방법
Tv t;
- Tv 클래스 타입의 참조변수 t를 선언
t = new Tv();
- Tv 인스턴스를 생성한 후, 생성된 Tv 인스턴스의 주소를 t에 저장

객체의 사용

TV 클래스
속성
- 색깔
- 전원상태
- 채널
기능
- 파워(전원)
- 채널 증가
- 채널 감소
TV1 인스턴스
속성
- 색깔 : 검정색
- 전원상태 : false
- 채널 : 1
기능
- 파워(전원)
- 채널 증가
- 채널 감소
class Tv1_1 {
    // 속성 : 변수 선언
    String color; // 색깔
    boolean power = false; // 전원상태 : false 로 초기화
    int channel = 1;  // 채널 : 1 로 초기화

    // 기능 : 메서드 선언
    void power() {  // 전원 기능
        power = !power;
        if (power) {
            System.out.println("전원 ON");
        } else {
            System.out.println("전원 OFF");
        }
    }

    void channelUp() { // 채널 증가
        channel++;
        System.out.println("채널 증가");
    }

    void channelDown() { // 채널 감소
        channel--;
        System.out.println("채널 감소");
    }
}

class Tv1_1Main {
    public static void main(String[] args) {
        Tv1_1 t1 = new Tv1_1(); // TV1 인스턴스
        t1.color = "검정색"; // 색깔 초기화
        Tv1_1 t2 = new Tv1_1(); // TV2 인스턴스
        t2.color = "흰색"; // 색깔 초기화

        System.out.println("TV1 인스턴스 색깔 = " + t1.color);
        System.out.println("TV2 인스턴스 색깔 = " + t2.color);

        t1.power(); // 메서드 호출
        System.out.println("TV1 인스턴스 채널 = " + t1.channel);

        t1.channelUp(); // 메서드 호출
        System.out.println("TV1 인스턴스 채널 : " + t1.channel);
        t1.channelDown(); // 메서드 호출
        System.out.println("TV1 인스턴스 채널 : " + t1.channel);

        t1.power(); // 메서드 호출


        // TV2 인스턴스 참조변수에 TV1 인스턴스의 주소 저장 했을 때
        t2 = t1;

        System.out.println("TV1 인스턴스 색깔 = " + t1.color); // 검정색
        System.out.println("TV2 인스턴스 색깔 = " + t2.color); // 검정색

        // 흰색이었던 TV2 인스턴스 의 색깔이 검정색으로 바뀐건가요?
        // 아닙니다.
        // 참조변수 t2 에 저장되어있던 TV2 인스턴스 의 주소가 없어지고
        // TV1 의 주소가 t2 참조변수에 저장이 됩니다

        // 따라서 t2 = t1; 이후 부터는
        // t2 참조변수로는 더 이상 TV2 인스턴스 에 접근할 수 없습니다.

    }
}

변수의 종류

선언 위치에 따른 변수의 종류

클래스 영역 : 클래스 변수
- 클래스가 메모리에 올라갈 때 생성된다.
- 객체 생성을 하지 않아도 생성되고 언제든지 사용 가능하다.
- 접근 방법 : 클래스명.클래스변수명
클래스 영역 : 인스턴스 변수
- 객체가 생성될 대 인스턴스 변수가 생성된다.
- 접근 방법 : 참조변수명.인스턴스변수명
메서드 영역 : 지역변수
- 메서드가 호출되서 실행될 때 생성된다.
메서드가 종료되면 자동으로 제거된다.

클래스 변수와 인스턴스 변수에 대해 잘 이해되지 않으면 영상을 보면 이해가 쉬울 것 같다.

class Obj4_1 {
    int iv;        // 인스턴스 변수
    static int cv; // 클래스 변수(static 변수, 공유 변수)

    void method() {
        int lv;
        lv = 30;
        // 지역변수는 자동으로 초기화가 되지 않기 때문에 사용하려면 반드시 초기화 필요
        System.out.println("lv 지역 변수 = " + lv);
    }
}


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

        // 클래스 변수 접근 및 사용
        // 접근방법 : 클래스명.클래스변수이름
        Obj4_1.cv = 10;
        System.out.println("ObjVar.cv 클래스 변수 = " + Obj4_1.cv);

        // 인스턴스 변수 생성 및 사용
        // Obj4_1.iv = 20; // Error, 인스턴스를 통해서만 생성 및 사용 가능
        Obj4_1 objVar = new Obj4_1();
        objVar.iv = 20;
        System.out.println("objVar.iv 인스턴스 변수 = " + objVar.iv);

        // 지역 변수 생성 및 사용
        // objVar.lv // Error, 인스턴스로 지역 변수 바로 접근 불가능
        objVar.method(); // 메서드 호출 시 지역 변수 생성
        // 메서드 종료시 지역 변수 삭제
    }
}

static 메서드와 인스턴스 메서드

static 메서드(클래스 메서드)

객체 생성 없이 '클래스이름.메서드이름()'으로 호출 : ex) Math.random()
인스턴스 멤버 (인스턴스 변수, 인스턴스 메서드)와 관련없는 작업을 하는 메서드
메서드 내에서 인스턴스 변수 사용 불가
class StaticMethod7_1 {
    int num1, num2; // 인스턴스 변수 선언

    // 클래스 변수 선언
//    static int num1 = 10, num2 = 20;

    static int add(int num1, int num2) { // 메서드 반환타입 앞에 static 이 붙었기 때문에 static 메서드가 됩니다.

        System.out.println();
        System.out.println("매개변수로 입력 받은 num1, num2 확인");
        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);

        // 여기서 매개 변수에 있는 num1, num2 와 위에 인스턴스 변수로 선언한 num1, num2 는 같은 걸까요?
        // 기본형 매개변수에서 배웠듯이 같지 않습니다. 서로 영향을 받지 않습니다.

        // 여기서의 num1 과 num2 는 단지 인스턴스 변수와 이름만 같은 지역변수일 뿐 메서드가 종료되면 사라집니다.
        // 인스턴스 변수는 클래스 메서드에서 사용하지 못합니다.

        // 그렇다면 추가로 StaticMethod7_1 에 선언한 변수를 사용하고 싶다면?
        // 인스턴스 변수가 아닌 클래스 변수를 선언해야합니다. static 타입 변수이름;

        // 위에 클래스 변수의 주석을 풀고 인스턴스 변수는 주석을 해주세요!

        // 자 그럼 이제 클래스 변수로 선언을 했으니까
        // 매개 변수에 있는 num1, num2 와 위에 클래스 변수로 선언한 num1, num2 는 같은 걸까요?
        // 그렇지 않습니다. 위에서 말씀드렸듯이 num1, num2는 매개변수이자 클래스 변수와 이름만 같습니다.
        // 또한 클래스 변수 를 사용하려면 클래스명.클래스변수 로 만 접근 가능합니다.

        // 이렇게 클래스 메서드에서 클래스 변수를 사용할 수 있습니다. 아래 주석 풀어주세요!

//        System.out.println("클래스변수 확인");
//        System.out.println("StaticMethod7_1.num1 = " + StaticMethod7_1.num1);
//        System.out.println("StaticMethod7_1.num2 = " + StaticMethod7_1.num2);

        System.out.println("num1 + num2 = " + (num1 + num2));
        return num1 + num2;
    }


}

class StaticMethod7_1Main {

    public static void main(String[] args) {
        StaticMethod7_1 methodTest = new StaticMethod7_1(); // 객체 생성
        methodTest.num1 = 10;
        methodTest.num2 = 20;

        // methodTest.add(methodTest.num1, methodTest.num2); // add 는 static 메서드 이기 때문에 객체로 생성된 참조변수로는 접근할 수 없습니다.

        // 클래스이름.메서드이름() 방식으로 static 메서드를 호출
        StaticMethod7_1.add(methodTest.num1, methodTest.num2);
    }
}

인스턴스 메서드

인스턴스를 생성한 후, '참조변수.메서드이름()'으로 호출
인스턴스 멤버(인스턴스 변수, 인스턴스 메서드)와 관련된 작업을 하는 메서드
메서드 내에서 인스턴스 변수 사용가능
class InstMethod7_1 {
    int num1, num2; // 인스턴스 변수 선언
    static int num3 = 100;

    int add(int num1, int num2) { // 메서드 반환타입 앞에 static 이 없기 때문에 인스턴스 메서드 입니다.

        System.out.println();
        System.out.println("매개변수로 입력 받은 num1, num2 확인");
        System.out.println("num1 = " + num1);
        System.out.println("num2 = " + num2);

        // 계속된 실습으로 우리는 위에 매개변수 num1, num2 와 InstMethod7_1 의 인스턴스 변수는 다르다는 것을 알았습니다.
        // 그럼 이런 의문이 듭니다. InstMethod7_1 클래스로 methodTest 객체를 생성했고
        // 참조변수를 통해 methodTest.num1 = 10;와 같이 인스턴스 변수에 값도 넣었는데
        // 저 값을 매개변수로 받는 의미가 있는 건가? 확인해 보겠습니다.

        // 인스턴스 변수 값 확인 : this 는 뒤에서 배우기 때문에 간단히 설명드리자면 인스턴스 변수와 매개변수를 구분하기 위한 것입니다.
        System.out.println("this.num1 = " + this.num1);
        // 10 이렇게 10이 출력될겁니다. 그럼 비교를 위해 아래 methodTest.add(methodTest.num1, methodTest.num2);
        // 주석 하고 methodTest.add(80,90); 주석을 푸세요!

        System.out.println("매개변수 이자 지역변수 num1 = " + num1);
        // 값이 달라졌을 겁니다. 이제 인스턴스 num1 과 매개변수 num1 은 이름만 같을 뿐이라는 것을 아셨을 겁니다.
        // 그래서 구분을 위해 변수의 이름을 다르게 하거나 this 를 사용해서 구분해야 합니다.

        // 그럼 지금 상황에서는 매개 변수를 받지 않고
        // return this.num1 + this.num2; // 이렇게 해도 됩니다.

        // 이번에는 그럼 일반 메서드니까 클래스 변수는 사용하지 못 할까? 아래 주석 제거하세요!
         //         System.out.println("InstMethod7_1.num3 = " + InstMethod7_1.num3); // 당연하게도 사용 가능합니다!

        return num1 + num2;
    }


}

class InstMethod7_1Main {

    public static void main(String[] args) {
        InstMethod7_1 methodTest = new InstMethod7_1(); // 객체 생성
        methodTest.num1 = 10;
        methodTest.num2 = 20;

        // 참조변수를 사용하여 인스턴스 메서드 호출
        System.out.println("result : " + methodTest.add(methodTest.num1, methodTest.num2));
//         System.out.println("result : " + methodTest.add(80,90));

    }
}

오버로딩

한 클래스 안에 같은 이름의 메서드를 여러 개 정의하는 것
오버로딩의 성립 조건
1. 메서드 이름이 같아야 한다.
2. 매개변수의 개수 또는 타입, 위치가 달라야 한다.
3. 반환타입에는 영향을 받지 않는다.
사용하는 목적
- 매개변수 즉, 입력하는 값이 다르지만 같은 기능을 수행하는 경우가 많을 때 사용성 및 효율을 높이기 위해 오버로딩을 사용한다.

생성자

인스턴스가 생성될 때마다 호출되는 '인스턴스 초기화 메서드'이다.
- 인스턴스 생성 시 수행할 작업에 사용된다.
- 초기값이 필요한 인스턴스 변수의 값을 초기화 해준다.
생성 조건
- 이름이 클래스 이름과 같아야 한다.
- return 값이 없다.
- void는 붙이지 않는다.
오버로딩 가능하다.

기본 생성자

- 매개변수가 없는 생성자를 의미한다.
- 생성자를 하나도 선언되어 있지 않았을 때는 컴파일러가 자동으로 추가해 준다.
class Tv9_1 {
    // 속성 : 변수 선언
    boolean power; // 전원상태
    int channel;  // 채널
    String color; // 색깔
    long price; // 가격

    // 위 속성에서 필수로 초기값이 필요한 값들을 초기화 해주는 기본 생성자
    public Tv9_1() {
        power = false;
        channel = 1;
    }

    //  오버로딩 한 생성자 - 매장 진열 용 일 경우에는 가격과 색깔의 초기화가 필요합니다. this 는 이전 챕터에서 잠깐 봤었죠! 매개변수와 인스턴스변수를 구분하기 위해 사용하겠습니다.
    public Tv9_1(String color, long price) {
        power = false; // this.power, power 둘다 지금 상황에서는 인스턴스 변수를 명확하게 판단 할 수 있기 때문에 어떤걸 사용해도 상관 없습니다.
        channel = 1;
        this.color = color;
        this.price = price;
    }

    // 기능 : 메서드 선언
    void power() {  // 전원 기능
        power = !power;
        if (power) {
            System.out.println("전원 ON");
        } else {
            System.out.println("전원 OFF");
        }
    }

    void channelUp() { // 채널 증가
        channel++;
        System.out.println("채널 증가");
    }

    void channelDown() { // 채널 감소
        channel--;
        System.out.println("채널 감소");
    }

}

class Tv9_1Main {
    public static void main(String[] args) {
        // 기본 초기화된 Tv9_1 생성
        Tv9_1 tv = new Tv9_1();
        System.out.print("기본 생성자 TV: ");
        tv.power();

        // 진열 용 Tv9_1 생성
        Tv9_1 exTv = new Tv9_1("보라색", 3456789);
        System.out.print("오버로딩 생성자 TV: ");
        exTv.power();
        System.out.println("exTv.color = " + exTv.color);
        System.out.println("exTv.price = " + exTv.price);

        // 근데 이때 주의할 점!
        // 기본 생성자는 없고 오버로딩한 생성자만 있을 경우!
        // 컴파일러는 기본 생성자를 만들어주지 않기 때문에 기본 생성자를 사용하려고 하면 Error 발생!
        // 위 기본 생성자를 주석 하세요!!!!
        Tv9_1 tv2 = new Tv9_1(); // Error 발생, 기본 생성자가 없기 때문에 매개 변수를 넣으라고 intellij 가 요구합니다.

    }
}

this 와 this()

this

  • 인스턴스 자신을 가리키는 참조변수
  • 인스턴스 메서드(생성자 포함) 에서 사용 가능
  • 지역 변수와 인스턴스 변수를 구별할 때 사용
class Tv10_1 {
    // 속성 : 변수 선언
    boolean power; // 전원상태
    int channel;  // 채널
    String color; // 색깔
    long price; // 가격

    // 위 속성에서 필수로 초기값이 필요한 값들을 초기화 해주는 기본 생성자
    public Tv10_1() {
        this.power = false;
        this.channel = 1;
    }

    //  오버로딩 한 생성자 - 매장 진열 용 일 경우에는 가격과 색깔의 초기화가 필요합니다.
    public Tv10_1(String color, long price) {
        this.power = false;
        this.channel = 1;
        this.color = color;
        this.price = price;
    }

    // 기능 : 메서드 선언
    void power() {  // 전원 기능
        this.power = !power;
        if (this.power) {
            System.out.println("전원 ON");
        } else {
            System.out.println("전원 OFF");
        }
    }

    void channelUp() { // 채널 증가
        this.channel++;
        System.out.println("채널 증가");
    }

    void channelDown() { // 채널 감소
        this.channel--;
        System.out.println("채널 감소");
    }

    // 색깔을 수정하고 자기 자신을 반환하는 메서드
    Tv10_1 changeColor(String color) { // 반환 타입으로 자기자신인 Tv 선언
        this.color = color;
        System.out.println("색깔 변경 완료!");
        return this; // this 는 자기 자신을 가리키는 참조변수!
    }

}

class Tv10_1Main {
    public static void main(String[] args) {
        // 기본 초기화된 Tv10_1 생성
        Tv10_1 tv = new Tv10_1();
        System.out.print("기본 생성자 Tv10_1: ");
        tv.power();

        // 진열 용 Tv10_1 생성
        Tv10_1 exTv = new Tv10_1("보라색", 3456789);
        System.out.print("오버로딩 생성자 Tv10_1: ");
        exTv.power();
        System.out.println("exTv.color = " + exTv.color);
        System.out.println("exTv.price = " + exTv.price);
        System.out.println();

        // 진열 용 Tv10_1 의 색깔을 수정하고 수정된 객체를 참조변수에 저장하겠습니다.
        Tv10_1 exTvThis = exTv.changeColor("파란색");
        // 색깔이 변경된 Tv의 주소가 저장된 참조변수 exTvThis 를 사용하여 변경된 색깔 확인
        System.out.println("색깔이 변경되었는지 확인 exTvThis.color : " + exTvThis.color);
        // 당연히 exTv 이걸로 확인해도 색깔이 변경되어 있습니다.
        System.out.println("exTv.color = " + exTv.color);
    }
}

this()

  • 생성자에서 다른 생성자를 호출할 때 사용한다.
    • this()를 사용하지 않고 클래스명(); 이렇게 생성자를 호출하려고 하면 Error가 발생한다.
  • 다른 생성자 호출 시 첫 줄에서만 사용 가능하다.
class Tv10_2 {
    // 속성 : 변수 선언
    boolean power; // 전원상태
    int channel;  // 채널
    String color; // 색깔
    long price; // 가격

    // 위 속성에서 필수로 초기값이 필요한 값들을 초기화 해주는 기본 생성자
    public Tv10_2() {
        this.power = false;
        this.channel = 1;
    }

    //  오버로딩 한 생성자 - 매장 진열 용 일 경우에는 가격과 색깔의 초기화가 필요합니다.
    public Tv10_2(String color, long price) {
        // 아래 초기화 내용은 위에 기본생성자와 완전히 똑같습니다.
        // 이럴 때 this() 를 사용합니다.
        // this.power = false;
        // this.channel = 1;

        this(); // 기본 생성자를 호출합니다.
        // Tv10_2() // 이렇게는 불가능 합니다! 

        this.color = color;
        this.price = price;

        // this(); // 생성자 호출은 반드시 첫 줄에서만 가능합니다.
    }

    // 기능 : 메서드 선언
    void power() {  // 전원 기능
        this.power = !power;
        if (this.power) {
            System.out.println("전원 ON");
        } else {
            System.out.println("전원 OFF");
        }
    }

    void channelUp() { // 채널 증가
        this.channel++;
        System.out.println("채널 증가");
    }

    void channelDown() { // 채널 감소
        this.channel--;
        System.out.println("채널 감소");
    }

    // 색깔을 수정하고 자기 자신을 반환하는 메서드
    Tv10_2 changeColor(String color) { // 반환 타입으로 자기자신인 Tv 선언
        this.color = color;
        System.out.println("색깔 변경 완료!");
        return this; // this 는 자기 자신을 가리키는 참조변수!
    }

}

class Tv10_2Main {
    public static void main(String[] args) {
        // 기본 초기화된 Tv10_2 생성
        Tv10_2 tv = new Tv10_2();
        System.out.print("기본 생성자 Tv10_2: ");
        tv.power();

        // 진열 용 Tv10_2 생성
        Tv10_2 exTv = new Tv10_2("보라색", 3456789);
        System.out.print("오버로딩 생성자 Tv10_2: ");
        exTv.power();
        System.out.println("exTv.color = " + exTv.color);
        System.out.println("exTv.price = " + exTv.price);
        System.out.println();

        // 진열 용 Tv10_2 의 색깔을 수정하고 수정된 객체를 참조변수에 저장하겠습니다.
        Tv10_2 exTvThis = exTv.changeColor("파란색");
        // 색깔이 변경된 Tv의 주소가 저장된 참조변수 exTvThis 를 사용하여 변경된 색깔 확인
        System.out.println("색깔이 변경되었는지 확인 exTvThis.color : " + exTvThis.color);
        // 당연히 exTv 이걸로 확인해도 색깔이 변경되어 있습니다.
        System.out.println("exTv.color = " + exTv.color);
    }
}