브래의 슬기로운 코딩 생활
JAVA 프로그래밍 7주차 정리 본문
상속과 다형성
Inheritance(상속)
what
• 기존의 클래스가 가지고 있는 변수와 메소드를 기반으로 필요한 변수와 메소드를 추가하거나
기존 메소드를 수정하여 새로운 클래스를 정의하는 것
• 기존 메소드의 수정을 재정의(overriding)라고 함.
why or benefits
• 비슷한 유형의 코드를 재사용하여 생산성이 높고 클래스 구조가 간소해진다
• 코드를 복사하는 방식이 아니기 때문에 효율적이다
• 검증된 코드를 사용하기 때문에 안정성이 증대된다.
• 오류를 줄일 수 있다.
• 재정의, 중첩으로 유연성과 확장성이 증대된다.
상속 관계
접근 수정자(access modifier)
필드, 메소드에 대한 접근 권한을 제어함
private은 선언된 클래스나 그 클래스로부터 직접 생성된 객체만 접근 가능함
private 필드는 상속 시 오류가 발생함
- private ➔ public으로 변경해서 해결
- 재정의해서 해결
- 접근 메소드(setter, getter) 제공을 통한 해결
private으로 정의되지 않은 인스턴스 변수와 메소드는 하위 클래스에서 사용할 수 있음
- 생성자의 경우 private으로 정의되지 않았지만 하위 클래스에서 사용할 수 없음
super vs. this
공통점
- 객체 생성 후 사용할 수 있는 예약어
super
수퍼 클래스의 메소드나 데이터를 접근할 때 사용되는 예약어
- 상위 클래스의 메소드 접근 : super.MethodName([ArgumentList]);
this
- 클래스로부터 생성되는 객체 자신을 나타내는 예약어
- 예)
public Integer(int value) { // 생성자
this.value = value; // 객체의 value 값을 배정
}
재정의와 중첩
시그니쳐(signature)
- 메소드 이름, 매개변수 개수, 매개변수 유형
재정의(overriding)
수퍼 클래스의 메소드와 시그니쳐가 같은 메소드를 만드는 것
- 서브 클래스로부터 생성된 객체는 재정의한 수퍼 클래스의 메소드를 접근할 수 없음
중첩(overloading)
메소드 이름은 같고 나머지 시그니쳐가 다른 메소드를 만드는 것
- 메소드 선언과 동일할 작업이고,
- 시그니쳐가 다른 경우, 반환 유형이 달라져도 됨
재정의하는 메소드는 기존 메소드와 같거나 더 넓은 접근 범위를
나타내는 접근 수정자로 재정의 되어야 함
- private -> private, default, protected, public
- default -> default, protected, public
- protected -> protected, public
- public -> public
예외 처리시 같은 예외 형식이거나 같은 종류의 예외 형식이어야 함
Object 클래스
모든 클래스의 상위 클래스, 즉 모든 클래스는 Object 클래스로부터 파생된다.
toString() : 데이터형과 객체의 해시 정보를 출력
- <package>.<className>@<hashcodeUsingHex>
equals() : 객체 참조변수의 비트 패턴이 같은 지만을 판별
상속받는 클래스에서 재정의 해서 사용함
String의 equals() : 문자열의 내용이 같은 지를 비교하도록 재정의 하여 사용함
final
final 메소드는 재정의가 불가함
- 재정의를 시도하는 경우 오류가 발생함
final 클래스의 모든 메소드는 묵시적으로 final 메소드임
- public class FinalClass extends String {
}
// Error : cannot inherit from final java.lang.String
static
- 클래스가 사용되는 시점에서 메모리에 적재되어 메소드 사용이 가능함.
객체마다 존재하지 않고, 클래스 단위로 존재함
- static 메소드 내부에서는 non-static 메소드와 필드를 참조할 수 없음
- static 메소드 내부에서는 this, super 예약어를 사용할 수 없음
상속과 생성자
상속 관계가 있는 두 클래스에서 서브 클래스로부터 객체를 생성할 경우
실행 순서
- 클래스 변수, 클래스 메소드 적재
- 수퍼 클래스의 인스턴스 변수 초기화 실행
- 수퍼 클래스의 생성자 실행
- 서브 클래스의 인스턴스 변수 초기화 실행
- 서브 클래스의 생성자 실행
호출된 생성자의 첫 줄에는 상위 클래스가 있는 경우 상위 클래스의 디폴트 생성자 호출이 생략되어 있는 것으로 처리함
수퍼, 서브 클래스 모두 생성자가 없는 경우
- 컴파일러가 디폴트 생성자를 수퍼 클래스와 서브 클래스에 삽입
생성자가 있는 경우
- 디폴트 생성자는 삽입되지 않기 때문에 명시적으로 디폴트 생성자를 삽입해야 함.
- super([ArgumentList]);를 삽입해서 다른 생성자를 호출해야 함
상위 클래스 생성자 호출
- super([ArgumentList]);
클래스 내 다른 생성자 호출
- this([ArgumentList]);
생성자 관련 상속 관계
- 생성자가 정의된 경우 하위 클래스 생성자는 상위 클래스의 디폴트 생성자를 자동으로 호출함
- 생성자가 정의되지 않은 경우 하위 생성자 첫 줄에 호출하려는 상위 생성자와
같은 인자정보를 가진 super(매개변수);를 삽입해야 함
- 상위 클래스, 하위 클래스 모두 생성자를 정의하지 않은 경우 오류 발생하지 않음
- 상위 클래스에 생성자가 존재하는 경우, 하위 클래스에서는 명시적으로 호출해야 함
다형성(polymorphism)
정의
객체의 종류에 따라 동일한 메시지(대상 객체 이름, 메소드, 매개변수)가 다른 연산을 수행하도록 하는 것
예)
- 에어컨.동작한다() / 온풍기.동작한다()
- 요금을 낸다(성인객체) / 요금을 낸다(청소년객체)
다형성이 있는 메시지는 컴파일 시가 아니라, 실행 시에 구체적으로 호출되는 연산을 결정됨
장점
코드의 중복을 줄여주고, 프로그램 변경을 최소화하면서 프로그램 확장 및 유지보수가 가능하도록 함
클래스(객체참조형) 형변환
업캐스팅 (묵시적인 형변환 가능)
- 메소드 감추기 또는 기능 감추기(invisible)
- 서브 클래스 형 객체를 수퍼 클래스 형으로 변환
- 서브 클래스의 멤버 변수와 메소드 중 수퍼 클래스에 구현된 부분만 사용이
가능하도록 제한함
- Object obj = new StringBuffer("UpCasting");
• obj는 다운캐스팅이 되기전까지 Object 클래스에 구현된 부문만 사용이 가능하다.
• obj.length()를 호출하는 경우 오류가 발생함
다운캐스팅 (명시적인 형변환이 필수적으로 필요함)
- 업캐스팅된 상위 클래스 형의 객체를 상속관계가 있는 하위 클래스 형으로 변환
▪ String str = (String) obj;
▪ obj가 참조하는 객체는 본래 StringBuffer 클래스를 업캐스팅한 객체라면 String 클래스로 형변환을 할 수 없다.
- 참고 : instanceof 연산자를 이용하여 참조하는 객체의 유형 확인
▪ if(obj instanceof StringBuffer) : ture를 반환함
▪ if(obj instanceof String) : false를 반환함
추상클래스와 인터페이스 (Abstract Class & Interface)
추상 클래스(abstract class)
What
서브 클래스를 정의하는 기준을 제시하기 위해 하나 이상의 추상 메소드를 갖는 클래스
- 추상 메소드 : 구현 코드가 없이 선언만으로 구성된 메소드
Why or Benefits
- 높은 유연성과 확장성을 제공하기 위한 방법
- 일관성 있는 설계가 가능함
추상 클래스 선언
Syntax
[public] abstract class <className> {
<fieldDeclarations>
<methodDeclarations>
[<abstractMothod>]
}
- private, final 예약어는 사용할 수 없음
특징
추상 메소드가 존재하기 때문에 인스턴스를 생성할 수 없음
단일 상속만을 가능함
- 하나의 추상 클래스만을 상속받을 수 있음. 즉 extends 예약어 뒤에는 하나의 추상 클래스만 가능함
추상 메소드를 구현할 때 접근 수정자는 항상 일치해야 함
상속을 통해 서브 클래스를 정의하는 경우 모든 추상 메소드가 구현되어야 함
상속을 통해 서브 추상 클래스를 정의하는 경우
- 상속받은 추상 메소드를 구현하거나 새로운 추상 메소드를 삽입할 수 있음
- 추상 메소드가 존재하여도 됨
자바 인터프리터가 실행시간에 해당 메소드를 적절하게 선택하여 동작 시킴(동적 바인딩)
- 재정의된 메소드를 호출하는 경우 객체 참조 변수가 참조하는 객체의 유형을 고려해서 메소드가 호출됨
▪ 컴파일 시에는 참조 변수의 유형을 고려함
인터페이스(interface)
What
- 모든 메소드는 추상 메소드이고, public static final 속성을 갖는 인스턴스 변수들로 구성된 프로그램 구성 요소
- 상수와 추상 메소드들로 구성된 설계의 표현
Why or Benefit
기능의 외부적 명시화에 유용
- 클래스의 정의를 알지 못해도, 구현된 객체의 사용법을 명료하게 알 수 있음
아주 높은 유연성을 제공함
- 서로 관련성이 떨어지는 클래스를 특별한 상속 관계 없이 연결하여 사용할 수 있음
하나 이상의 클래스를 통해서 구현해야 하는 메소드 선언 시 사용
인터페이스 선언
Syntax
[public] interface InterfaceName
[extends ListOfSuperInterface] {
<constantDefinitions>
[<abstractMothod>]
}
수퍼 인터페이스 : 상속해주는 인터페이스
▪ 수퍼 인터페이스는 복수개가 나타날 수 있음
▪ interface MultiInheritInterface
extends SuperInterface1, SuperInterface2
서브 인터페이스 : 상속을 받는 인터페이스
특징
다중 상속이 가능함
모든 메소드는 묵시적으로 public임
- static일 수 없음
모든 인스턴스 변수는 묵시적으로 public static final 속성을 가짐
- 초기화가 필요함
생성자는 없음 : 객체 생성이 아닌 설계가 목적임
private, protected, synchronized, volatile 사용 할 수 없음
인터페이스와 상속
- 메소드 상속 시 Signature가 같은 메소드는 반환유형도 같아야 함, 다른 경우 오류 발생
- 메소드 상속 시 Signature가 다른 경우 중첩
- 인터페이스 이름과 함께 인스턴스 변수를 기술하기 때문에 모호성이 발생하지 않음
다중 상속의 문제점
모호성(ambiguity) : 참조하는 필드나 메소드의 출처가 혼동되는 문제
- 예) 시그니쳐가 같은 메소드를 갖는 두 수퍼 클래스들을 다중상속한 경우 서브 클래스로부터 생성한 객체가
메소드를 호출하면 어느 수퍼 클래스의 메소드인지 혼동된다.
자바에서는 인터페이스 다중 상속을 지원하므로, 객체를 생성하기
위해서는 구현을 해야 하기 때문에 출처를 명확하게 알 수 있다.
인터페이스 구현
• Syntax
[<classModifiers>] class <ClassName>
implements <InterfaceName1>, …
{
// instance variable declarations
// methods declarations
}
다이아몬드 상속
수퍼 클래스로부터 상속을 받고, 인터페이스로 부터 구현하는 상속 관계
• 예)
interface SuperInterface1 { }
interface SuperInterface2 { }
interface ExtendedInterface extends SuperInterface1 {}
abstract class SuperClass implements SuperInterface1{}
class DiamondInheritance extends SuperClass
implements ExtendedInterface
다이아모든 상속과 다중 구현
class DiamondMultiple extends SuperClass
implements SuperIterface2, ExtendedInterface
비교
중첩 클래스(nested class)
what
- 다른 클래스 내부나 블록 내부에 선언된 클래스
- inner class, static nested class, local class, anonymous class
why or benefits
- 클래스 참조 범위를 제한하여 이름 충돌(name conflicts) 문제를 해결할 수 있음
- 연관된 클래스들을 논리적으로 하나의 클래스에 모을 수 있기 때문에 가독성과 유지보수성이 향상됨
- 내부 클래스의 구현의 외부 노출을 방지함으로써 캡슐화가 더 향상됨
syntax
- class OuterClass {
// outer class body
class InnerClass {
// inner class body
}
static class StaticNestedClass {
// static nested class body
}
}
지역 클래스(local class)
블록({ ~ }) 내부 또는 메소드 바디에 선언된 클래스
특징
- 유효 범위, 즉 참조 가능한 범위가 메소드 바디 또는 블록 내부로 한정됨
- 컴파일이 생성되면 LocalClassTest.class와
LocalClassTest$1LocalClass.class 가 생성됨
익명 클래스(anonymous class)
선언과 동시에 인스턴스화를 수행하는 클래스
클래스 이름이 없는 클래스, 컴파일을 수행하면 <className>$1.class ,
<className>$2.class 등의 파일이 생성됨
syntax
<ClassName> <referenceVariable> = new <ClassConstructor>() {
//class body
}
why or benefits
코드 간소화됨
'2-1 > JAVA 프로그래밍' 카테고리의 다른 글
JAVA 프로그래밍 10주차 정리 (2) | 2023.05.09 |
---|---|
JAVA 프로그래밍 중간고사 정리 (0) | 2023.04.29 |
JAVA 프로그래밍 6주차 정리 (0) | 2023.04.11 |
JAVA 프로그래밍 5주차 정리 (0) | 2023.04.04 |
JAVA 프로그래밍 4주차 정리 (0) | 2023.03.28 |