꾸양!
일단 시작.
꾸양!
💁‍♀️ 깃허브 링크
전체 방문자
오늘
어제
  • 분류 전체보기 (112)
    • STUDY (85)
      • JAVA (36)
      • Algorithm (1)
      • SpringBoot (9)
      • SQL (4)
      • GIT (16)
      • Front (1)
      • JPA (9)
      • Trouble Shooting (9)
    • SPARTA Project (26)
      • WIL (14)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 인프런
  • 코드효율성
  • Repository
  • 프로그래머스
  • 랠릿
  • 트러블슈팅
  • 숫자짝꿍
  • 클린코드
  • intellij
  • 인프콘2024
  • 잔디돌려줘

최근 댓글

최근 글

hELLO · Designed By 정상우.
꾸양!

일단 시작.

STUDY/JAVA

230404 공부기록

2023. 4. 11. 23:54

* 추상클래스
  구체적이지 않은 클래스.

    - 정의하기
        - 클래스 앞에 abstract 키워드를 이용해서 정의한다.
        - 미완성의 추상 메소드를 포함할 수 있다.
        - 일반 메소드도 가질 수 있다.
        - 추상 클래스는 인스턴스를 생성할 수 없다.

    - 추상 메소드
        - 내용이 없는 메소드 , 즉 구현이 되지 않은 메소드
        - 추상 메소드는 리턴 타입 앞에 abstract라는 키워드를 붙여야 한다.

    - 추상 클래스를 상속받는 클래스 생성
        - 추상 클래스를 상속받은 클래스는 추상 클래스가 갖고 있는 추상 메소드를 반드시 구현해야 한다.
        - 추상 클래스를 상속받고, 추상 클래스가 갖고 있는 추상 메소드를 구현하지 않으면 해당 클래스도 추상 클래스가 된다.

    - 추상클래스의 사용용도
        -  추상클래스의 사용용도는 추상 메소드가 포함된 클래스를 상속받는 자식 클래스가 반드시 추상 메소드를 구현하도록 하기 위함. (예 : 모듈처럼 중복되는 부분이나 공통적인 부분은 미리 다 만들어진 것을 사용하고, 이를 받아 사용하는 쪽에서는 자신에게 필요한 부분만을 재정의하여 사용함으로써 생산성이 향상되고 배포 등이 쉬워지기 때문.)

* 어노테이션
  클래스나 메소드, 변수에 @을 사용하는 것.

    - 어노테이션을 사용하는 이유
        - 어노테이션은 사전적 의미로 주석. 주석과는 역할이 다르지만, 주석처럼 달아 특수한 의미 부여가 가능하며, 기능 주입이 가능. 어노테이션을 사용하는 가장 큰 이유는 프로그램에게 추가 정보를 제공하는 메타 데이터를 위해서 사용.

    - @Override 어노테이션의 기능
        - 자식 클래스에 여러 개의 메소드가 정의가 되어 있을 경우
          해당 메소드가 부모 클래스에 있는 메소드를 Override 했다는 것을 명시적으로 선언.
          가령 어노테이션을 사용하지 않으면 자식 클래스에 여러 개의 메소드가 있을 경우, 어떤 메소드가 Override 되었는지 쉽게 알기 어려움.
          이 때, 오버라이드 메소드를 사용하여 명시적으로 선언하게 되면 많은 메소드 중에서 어떠한 메소드가 부모 클래스로부터 오버라이딩이 되었는지 쉽게 파악할 수 있음. 실제로 본인이 작성한 코드는 쉽게 파악이 가능하겠지만, 다른 사람이 작성한 코드일 경우에는 알아보기가 어려울 수밖에 없음.
        - 컴파일러에게 문법 체크를 하도록 알림.
          오버라이딩을 하기 위해서는 부모 클래스의 있는 메소드명과 매개변수를 동일하게 가져가야 한다. 그런데 제대로 오버라이딩을 했다고 생각했는데, 매개변수를 잘못 지정했을 수도 있다. 따라서 해당 어노테이션을 사용하면 "이 메소드는 Override 된 거야!"라고 컴파일러에게 알려 컴파일시 체크를 할 수 있다.

* super와 부모생성자

public class Car {
    public Car(String name) {
        System.out.println("Car의 "+name+"생성자입니다.");
    }

public class Truck extends Car {
    public Truck() {
        System.out.println("Truck의 기본생성자입니다.");
    }
}

public class TruckExam {
    public static void main(String[] args) {
        Truck t = new Truck();
    }
}

    - 위처럼 코드를 짜면 오류가 난다. 트럭이 생성되려면 반드시 부모가 먼저 생성되어야 하는데 부모의 생성자를 내가 호출하지 않으면 컴파일러는 부모의 기본생성자만 호출하게 되어 있다.(super();) 그런데 부모클래스는 더 이상 기본생성자를 가지고 있지 않으므로 오류가 난다.
    - Truck 클래스의 기본생성자 블록에서 super("소방차");를 첫줄에 넣어주거나 Car 클래스에서 기본 생성자를 따로 선언해주면 된다.
    - super : 부모를 가리키는 키워드

* 오버라이딩(Overriding)
  부모가 가지고 있는 메소드와 똑같은 모양의 메소드를 자식이 가지고 있는 것, 메소드를 재정의 하는 것. (override는 우선시하다라는 뜻이 있다.)

    - 메소드 오버라이딩
        - 메소드를 오버라이드 하면, 항상 자식클래스에서 정의된 메소드가 호출된다.
        - 오버라이딩 한다고 해서 부모의 메소드가 사라지는 것은 아니다.
        - super 키워드를 이용하면, 부모의 메소드를 호출 할 수 있다.

public class OverrideChild extends OverrideParent {
    public void run() {
        System.out.println("오버라이드 '자식'의 run 메소드");
    }
}

자식클래스의 run 메소드를 호출할 때, 부모의 run 메소드도 같이 호출하고 싶다면, 자식 클래스의 run 메소드 블록 첫 줄에 super.run(); 을 추가해주면 된다.

* 클래스 형변환(Class Casting)

    - 부모타입으로 자식객체를 참조하게 되면 부모가 가지고 있는 메소드만 사용할 수 있다.
    - 자식객체가 가지고 있는 메소드나 속성을 사용하고 싶다면 형변환 해야 한다.

    클래스 형병환이 너무 어려운 개념이었다. 부모타입으로 자식객체를 참조한다라는 개념이 이해가 잘 안되었다. 그래서 강의 질문을 보니 나와 같은 생각을 하고 질문을 한 사람이 있었다. 질문의 답변을 보니 객체지향, 객체 생성에 대한 이해가 더 필요한 거 같다고 해서 작성되어 있던 링크로 갔더니 좀 더 쉽게 이해가 가능했다.

++ 객체지향, 객체 생성에 대하여

public class CodeRunner {
    public static void main(String[] args) {
        attackSomething(new Knife());
        attackSomething(new Gun());
    }

    static void attackSomething(Weapon weapon) {
        weapon.attack();
    }
}
------------------------------------------------------------------------
abstract class Weapon {
    abstract void attack();
}
------------------------------------------------------------------------
public class Knife extends Weapon {
    void attack() {
        System.out.println("칼로 공격");
    }
}
-----------------------------------------------------------------------
public class Gun extends Weapon {
    void attack() {
        System.out.println("총으로 공격");
    }
}

적은 양의 복잡성을 갖고 있는 코드에서 굳이 상속을 해야 하나라는 의구심이 들 수도 있다.
하지만 상속(객체지향)은 결국 시스템 확장시에 효율성을 위함이다.

객체 지향의 중요한 특성 중 하나는 "특정 타입에 속하는 모든 객체는 동일한 메시지를 받을 수 있다.".
메시지를 보내는 행위는 객체의 메소드를 호출하는 개념..

메인 메소드의 attacksomething()은 베이스타입(부모클래스)인 Weapon을 매개변수로 지정함으로써, Weapon 클래스로부터 파생된 클래스의 객체를 모두 받아들일 수 있다.(여기서 다형성의 개념이 나온다.)

이렇게 해서 무기 추가의 요구 사항이 발생하더라도 기존 코드의 수정없이 새로운 무기 클래스를 작성할 수 있다.

* 인터페이스
  서로 관계가 없는 물체들이 상호 작용을 하기 위해서 사용하는 장치나 시스템

    - TV interface 만들기.
        - TV는 어떤 기능을 가지는가. 켜고 끄는 기능, 볼륨 조절 기능, 채널 변경 기능.
        - 어떻게 구현될지는 모르겠는데 이런 기능들이 있어~ 하는 것. >> 추상 메소드와 비슷하다.

++ 변수의 range 정하기

int MIN_VOLUME = 0;
int MAX_VOLUME = 100;

// VOLUME의 최소값은 0, 최대값은 100

    - TV 인터페이스의 기능을 LedTV도 갖게 하기.
public class LedTV implements TV { TV의 메소드 오버라이딩 }

TV tv = new LedTV();
        - 인터페이스도 타입이 될 수 있다.
        - TV 인터페이스가 LedTV 클래스를 구현했다.
        - 참조변수의 타입으로 인터페이스를 사용할 수 있다. 이 경우 인터페이스가 가지고 있는 메소드만 사용할 수 있다.

* 인터페이스의 default 메소드와 static 메소드
  JAVA 8이 등장하면서 interface에 대한 정의가 몇 가지 변경되었다.

    - default메소드
        - 인터페이스에서 메소드가 default 키워드로 선언되면 메소드가 구현될 수 있다.
        - 또한 이를 구현하는 클래스는 default 메소드를 오버라이딩 할 수 있다. 인터페이스가 변경이 되면, 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제가 있다. 이런 문제를 해결하기 위하여 인터페이스에 메소드를 구현해 놓을 수 있도록 하였다.

    - static메소드
        - 인터페이스에 static 메소드를 선언함으로써, 인터페이스를 이용하여 간단한 기능을 가지는 유틸리티성 인터페이스를 만들 수 있게 되었다.
        - 인터페이스의 static 메소드는 인터페이스명.메소드명()으로 사용가능하다.

* 내부클래스
  클래스 안에 선언된 클래스, 어느 위치에 선언하느냐에 따라서 4가지 형태가 있을 수 있다.

    1. 클래스 안에 인스턴스 변수, 즉 필드를 선언하는 위치에 선언되는 경우, 보통 중첩클래스 혹은 인스턴스 클래스라고 한다.

public class InnerExam1 {
    class Cal{
    int value = 0;
       public void plus() {
        value++;
       }
    }
    public static void main(String[] args) {
        InnerExam1 t = new InnerExam1();    // 내부클래스 사용방법 1. 외부클래스 객체화
        InnerExam1.Cal cal = t.new Cal();    // 2. 내부클래스 객체화
        cal.plus();
        System.out.println(cal.value);    // 출력 1
    }
}

    2. 내부 클래스가 static으로 정의된 경우, 정적 중첩 클래스 또는 static 클래스라고 한다.

public class InnerExam2 {
        static class Cal{
                int value = 0;
                public void plus() {
                        value++;
                }
        }
        public static void main(String[] args) {
                InnerExam2.Cal cal = new InnerExam2.Cal();
// 이 경우에는 외부클래스를 객체화할 필요없이 new InnerExam2.Cal() 로 객체를 생성할 수 있다.
                cal.plus();
                System.out.println(cal.value);
        }
}
      
    3. 메소드 안에 클래스를 선언한 경우, 지역 중첩 클래스 또는 지역 클래스라고 한다.
        - 메소드 내에서만 해당 클래스를 이용 가능.

    4. 익명클래스
public abstract class Action {
        public abstract void exec();
}
--------------------------------------------------------
public class ActionExam {
        public static void main(String[] args) {
                Action action = new Action() {
                @Override
                        public void exec() {
                                System.out.println("exec");
                        }
                }; // 꼭 세미콜론을 넣어주어야 한다.
                action.exec();
        }
}
    - 익명 중첩 클래스는 익명 클래스라고 보통 말하며, 내부 클래스이기도 하다.
    - 생성자 다음에 중괄호 열고 닫고가 나오면, 해당 생성자 이름에 해당하는 클래스를 상속받는 이름없는 객체를 만든다는 것을 뜻한다.
    - 괄호 안에는 메소드를 구현하거나 메소드를 추가할 수 있다. 이렇게 생성된 이름 없는 객체를 action이라는 참조변수가 참조하도록 하고, exec()메소드를 호출.
    - 익명클래스를 만드는 이유는 Action을 상속받는 클래스를 만들 필요가 없을 경우이다.
    - Action을 상속받는 클래스가 해당 클래스에서만 사용되고 다른 클래스에서는 사용되지 않는 경우이다.

저작자표시

'STUDY > JAVA' 카테고리의 다른 글

230409 공부기록  (0) 2023.04.11
230406 공부기록  (0) 2023.04.11
230403 공부기록  (0) 2023.04.04
230401 공부기록  (0) 2023.04.04
230331 공부기록  (0) 2023.04.01
    'STUDY/JAVA' 카테고리의 다른 글
    • 230409 공부기록
    • 230406 공부기록
    • 230403 공부기록
    • 230401 공부기록
    꾸양!
    꾸양!
    차근차근 한 발자국씩.

    티스토리툴바