JAVA 객체지향 프로그래밍 심화 1

grapefruit·2022년 9월 6일
0

BE 2022-09.05~09.08

목록 보기
1/2

상속

두 클래스를 상위 클래스와 하위 클래스로 나누어 상위 클래스의 멤버(필드, 메서드, 이너 클래스)를 하위 클래스와 공유하는 것을 의미한다.

여기서 우리는 이 두 클래스를 서로 상속 관계 있다고 하며, 하위 클래스는 상위 클래스가 가진 모든 멤버를 상속받게 된다.

그렇다면 왜 상속을 사용할까요?

결론적으로 말하자면, 상속을 통해 클래스를 작성하면 앞선 예제에서 확인할 수 있었던 것처럼 코드를 재사용하여 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있어 코드의 중복을 제거할 수 있다.
더 나아가, 상속은 다형적 표현이 가능하다는 장점이 있다.

주의!!
자바의 객체지향 프로그래밍에서는 단일 상속(single inheritance)만을 허용한다는 것이다. 다른 말로, 다중 상속은 허용되지 않는다.

포함 관계

포함(composite)

상속처럼 클래스를 재사용할 수 있는 방법으로, 클래스의 멤버로 다른 클래스 타입의 참조변수를 선언하는 것을 의미

메서드 오버라이딩

메서드 오버라이딩(Method Overriding)

상위 클래스로부터 상속받은 메서드와 동일한 이름의 메서드를 재정의하는 것을 의미

메서드 오버라이딩을 사용할 때 다음의 세 가지 조건을 반드시 만족

  1. 메서드의 선언부(메서드 이름, 매개변수, 반환타입)이 상위클래스의 그것과 완전히 일치해야한다.
  2. 접근 제어자의 범위가 상위 클래스의 메서드보다 같거나 넓어야 한다.
  3. 예외는 상위 클래스의 메서드보다 많이 선언할 수 없다.

super 키워드와 super()

this는 자신의 객체, this() 메서드는 자신의 생성자 호출을 의미한다.

이번에 배운 super 키워드와 super() 메서드도 이와 비슷하다고 할 수 있다.
super 키워드는 상위 클래스의 객체, super()는 상위 클래스의 생성자를 호출하는 것을 의미한다.

공통적으로 모두 상위 클래스의 존재를 상정하며 상속 관계를 전제한다.

두 개의 같은 이름의 변수를 구분하기 위한 방법이 바로 super 키워드

super 키워드를 붙이지 않는다면, 자바 컴파일러는 해당 객체는 자신이 속한 인스턴스 객체의 멤버를 먼저 참조한다.

반면 경우에 따라서 상위 클래스의 변수를 참조해야할 경우가 종종 있는데 그 경우 super 키워드를 사용하면 부모의 객체의 멤버 값을 참고할 수 있다.

즉, 상위 클래스의 멤버와 자신의 멤버를 구별하는 데 사용된다는 점을 제외한다면 this와 super는 기본적으로 같은 것이라 말할 수 있다.

super() 메서드

super() 메서드 또한 this()와 마찬가지로 생성자 안에서만 사용가능하고, 반드시 첫 줄에 와야 한다.

여기서 기억해야하는 가장 중요한 사실은 모든 생성자의 첫 줄에는 반드시 this() 또는 super()가 선언되어야 한다는 것이다.

만약 super()가 없는 경우에는 컴파일러가 생성자의 첫 줄에 자동으로 super()를 삽입한다.

이때 상위클래스에 기본생성자가 없으면 에러가 발생하게 된다.

Object 클래스

Object 클래스는 자바의 클래스 상속계층도에서 최상위에 위치한 상위클래스이다.
따라서 자바의 모든 클래스는 Object 클래스로부터 확장된다는 명제는 항상 참이다.

실제로 자바 컴파일러는 컴파일링의 과정에서 다른 클래스로부터 아무런 상속을 받지 않는 클래스에 자동적으로 extends Object를 추가하여 Object 클래스를 상속받도록 한다.

Object 클래스는 자바 클래스의 상속계층도에 가장 위에 위치하기 때문에 Object 클래스의 멤버들을 자동으로 상속받아 사용할 수 있다.

캡슐화

캡슐화

특정 객체 안에 관련된 속성과 기능을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호하는 것

이렇게 캡슐화를 해야하는 이유로 크게 두 가지 목적이 있습니다. 첫 째는 데이터 보호의 목적이고, 두 번째로 내부적으로만 사용되는 데이터에 대한 불필요한 외부 노출을 방지하기 위함

제어자(Modifier)

자바 프로그래밍에서 제어자는 클래스, 필드, 메서드, 생성자 등에 부가적인 의미를 부여하는 키워드를 의미

접근 제어자 -> public, protected, (default), private
기타 제어자 -> static, final, abstract, native, transient, synchronized 등

각 대상에 대해서 접근 제어자는 단 한번만 사용할 수 있다.

접근 제어자(Access Modifier)

접근 제어자를 사용하면 클래스 외부로의 불필요한 데이터 노출을 방지(data hiding)할 수 있고, 외부로부터 데이터가 임의로 변경되지 않도록 막을 수 있다.

접근 제한 범위에 따라서 표현하면,
public(접근 제한 없음) > protected(동일 패키지 + 하위클래스) > default(동일 패키지) > private(동일 클래스) 순으로 정리

우리는 접근 제어자를 통해 외부로부터 데이터를 보호하고, 불필요하게 데이터가 노출되는 것을 방지 할 수 있다.

또한 접근 제어자는 private, default, protected, public 4가지로 구분할 수 있고, 각각 다른 접근 제한 범위를 가진다.

getter와 setter 메서드

setter 메서드는 외부에서 메서드에 접근하여 조건에 맞을 경우 데이터 값을
변경 가능하게 해주고 일반적으로 메서드명에 set-을 붙여서 정의

getter 메서드는 설정한 변수 값을 읽어오는 데 사용하는 메서드

setter와 getter 메서드를 활용하면 데이터를 효과적으로 보호하면서도 의도하는 값으로 값을 변경하여 캡슐화를 보다 효과적으로 달성할 수 있다.

패키지

특정한 목적을 공유하는 클래스와 인터페이스의 묶음을 의미

클래스를 정의할 때 관련있는 속성과 기능을 묶어 데이터들을 효율적으로 관리할 수 있었듯, 패키지는 클래스들을 그룹 단위로 묶어 효과적으로 관리하기 위한 목적을 가지고 있다.

우리가 컴퓨터를 사용할 때 폴더를 만들어 그 폴더와 관련된 파일들을 관리하는 것과 유사하다고 할 수 있다.

자바에서 패키지는 물리적인 하나의 디렉토리(directory)이고, 하나의 패키지에 속한 클래스나 인터페이스 파일은 모두 해당 패키지에 속해있다.

더 나아가, 이 디렉토리는 하나의 계층구조를 가지고 있는데, 계층 구조 간 구분은 점(.)으로 표현된다.

마지막으로, 패키지가 있는 경우 소스 코드의 첫 번째 줄에 반드시 package 패키지명이 표시되어야 하고, 만약 패키지 선언이 없으면 이름없는 패키지에 속하게 된다.

1    // 패키지를 생성했을 때
2    package practicepack.test; // 패키지 구문 포함. 패키지가 없다면 구문     필요없음
3
4    public class PackageEx {
5
6    }

우리가 주로 사용하는 String 클래스의 실제 이름은 java.lang.String인데,
여기서 java.lang은 패키지명을 나타내고 점(.)을 사용하여 디렉터리 계층구조를 나타내고 있다.

이렇게 패키지로 클래스를 묶는 것의 또 하나의 장점은 클래스의 충돌을 방지해주는 기능에 있다.
예를 들면, 같은 이름의 클래스를 가지고 있더라도 각각 다른 패키지에 소속되어 있다면 이름명으로 인한 충돌이 발생하지 않는다.

Import문

다른 패키지 내의 클래스를 사용하기 위해 사용하며, 일반적으로 패키지 구문과 클래스문 사이에 작성한다.

import문은 다음과 같이 작성한다.

1 import 패키지명.클래스명; 또는 import 패키지명.*;
profile
개발자몽

0개의 댓글