Chapter7. 객체지향 프로그래밍II

상속( inheritance )

  • 기존의 클래스를 재사용하여 새로운 클래스를 작성한 것.

- 구현 방법

  • 클래스의 이름 뒤에 상속받고자 하는 클래스의 이름을 키워드 'extends'와 함 께 작성. ( ex. class Child extends Parents )

 

class Child extends Parent {

}

class Parent{}

 

 

- 특징

  • 생성자와 초기화 블록은 상속되지 않는다. 멤버만 상속된다.
  • 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다. 
  • 조상 클래스는 자손 클래스의 공통적인 부분을 가지고 있어 각 클래스의 코드가 적어져서 관리가 용이함.

클래스간의 관계

 

- 포함관계 (composite)

  • 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것을 뜻함. 

- 선언방법

  • Circle 클래스에 Point 클래스를 참조변수 c로 선언함.
class Circle{
	Point c = new Point();
}

 

- 클래스간의 관계 결정하기

  • (Circle) (Point)이다. - 해당 말이 옳다고 보면 상속관계.
  • (Circle) (Point) 가지고 있다. - 해당 말이 옳다고 보면 포함관계.

- 단일 상속(single inheritance)

  • 자바에서는 다중상속의 문제점을 해결하기 위해 다중상속의 장점을 포기하고 단일 상속만을 허용한다.

- Object 클래스 

  • 모든 클래스 상속계층도의 최상위에 있는 조상클래스이다.
  • 자바의 모든 클래스들은 Object클래스의 멤버들을 상속 받기 때문에 Object클래스에 정의된 멤버들을 사용할 있다.


오버라이딩(Overriding)

 

  • 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩이라고 한다.

 

class Point {
	int x;
    int y;

String getLocation() {
	return "x : " + x + ", y : " + y ;
	}
}

class Point3D extends Point {
	int z;
    return "x : " + x + ", y : " + y + ", z : " + z;
}

 

- 조건(자손 클래스에서 오버라이딩 하는 메서드는 조상 클래스의 메서드와)

  • 이름이 같아야 한다.
  • 매개변수가 같아야 한다.
  • 반환타입이 같아야 한다.

- 조상 클래스의 메서드를 자손 클래스에서 오버라이딩 할 때

  • 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경 없다.
  • 조상 클래스의 메서드보다 많은 수의 예외를 선언할 없다.
  • 인스턴스메서드를 static 메서드로 또는 반대로 변경 없다.

- 오버로딩 vs 오버라이딩

  • 오버로딩
    • 기존에 없는 새로운 메서드를 정의하는 (new)
  • 오버라이딩
    • 상속받은 메서드의 내용을 변경하는 (change, modify)

super

 

  • 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.
  • 조상 클래스의 멤버와 자손클래스의 멤버가 중복 정의되어 서로 구별 해야하는 경우에만 super를 사용.

- super()

  • Super() 조상 클래스의 생성자를 호출하는데 사용한다.
  • 조상 클래스 멤버의 초기화 작업이 수행되어야 하기 때문에 자손 클래스의 생성자에서 조상 클래스의 생성자가 호출되어야 한다

- 선언

  • Object클래스를 제외한 모든 클래스의 생성자 줄에 this(), super() 호출해야 한다.
  • 호출 하지 않아도 컴파일러가 자동적으로 super() 줄에 삽입하여 문제가 없다.
  • 조상 클래스의 멤버변수는 이처럼 조상의 생성자에 의해 초기화되도록 해야 한다.

 

Point3D(int x, int y, int z) {
	super();
    this.x = x;
    this.y = y;
    this.z = z;
}

Package import

 

- 패키지(package)

  • 클래스의 묶음.
  • 패키지에는 클래스 또는 인터페이스를 포함시킬 있다.
  • 클래스가 물리적으로 하나의 클래스파일 것과 같이 패키지는 물리적으로 하나의 디렉토리이다.

- 선언

  • 클래스나 인터페이스의 소스파일의 위에 선언하면 된다.

- Import문 

  • Import문으로 사용하고자 하는 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명을 생략 있다.
  • Ctrl + shift + o 자동으로 선언되게 있다.

-  static import 문

  • Static import문을 사용하면 static멤버를 호출할  클래스 이름을 생략가능.

제어자(modifier) - 캡슐화

 

  • 클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다.
  • 접근제어자
    • Public, protected, default, private
    • Static, final, abstract, native, transient, synchronized, volatile, strictfp

- static (클래스의, 공통적인)

  • 클래스변수는 인스턴스에 관계없이 같은 값을 가진다.
  • 하나의 변수를 모든 인스턴스가 공유를 한다.
  • Static 붙은 멤버변수와 메서드, 그리고 초기화 블록은 인스턴스 생성없이 사용가능하다.

- final(마지막의, 변경될 수 없는)

  • 변수에 사용되면 값을 변경 할 수 없는 상수가 되며, 메서드에 사용되면 오버라이딩을 할 수 없게 되고 클래스에 사용되면 자신을 확장하는 자손클래스를 정의하지 못하게 된다.
  • 생성자를 이용한 final멤버 변수의 초기화가 가능함.

- Abstract ( 추상의, 미완성의 )

  • '미완성' 의미를 가지고 있다. 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언하는데 사용한다.

- 접근 제어자 ( access modifier )

  • 멤버 또는 클래스에 사용되어, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할을 .
  • Private : 같은 클래스 내에서만 접근이 가능
  • Default : 같은 패키지 내에서만 사용이 가능
  • Protected : 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.
  • Public : 접근 제한이 전혀 없다.
  • Public > protected > (default) > private

- 접근 제어자를 이용한 캡슐화

  • 외부로부터 데이터를 보호하기 위해서
  • 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서

- 제어자의 조합

  • 메서드에 static abstract 함께 사용이 불가함.
  • 클래스에 abstract final 동시에 사용할 없다.
  • Abstract메서드의 접근 제어자가 private 없다.
  • 메서드에 private final 같이 사용할 없다.

다형성( polymorphism )

 

  • 여러 가지 형태를 가질 있는 능력
  • 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조 있도록 .

 

Tv t = new CaptionTv() ; // 조상 타입의 참조변수로 자손 인스턴스를 참조

 

- 특징

  • 같은 타입의 인스턴스지만 참조변수의 타입에 따라 사용 있는 멤버의 개수가 달라진다.
  • 참조변수가 사용할 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.
  • 반대로 자손타입이 참조변수로 조상타입의 인스턴스를 참조할 없다.

- 참조변수의 형변환

  • 자손타입 -> 조상타입 (up-casting) : 형변환 생략가능
  • 조상타입 -> 자손타입 (down-casting) : 형변환 생략불가

 

Car car = null;
FireEngine fe = new FireEngine();
FireEngine fe2 = null;

car = fe; // car = (Car)fe; 에서 형변환이 생략됨. 업캐스팅
fe2 = (FireEngine)car; // 형변환 생략불가. 다운캐스팅

 

  • Car차입의 참조변수 c  object 형변환시 생략이 가능한 것은 object 상위타입이기 때문이다.
  • 형변환은 참조변수의 타입을 변환한 것이지 인스턴스를 변환하는 것은 아니기 때문에 인스턴스에는 아무런 영향이 없다.
  • 조상의 인스턴스 객체를 가진 자손의 참조변수를 직접적으로 자손타입 참조변수에 넘기는 것은 불가능하다.
    • 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요하다.

- Instanceof연산자        

  • 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 사용됨.
  • Instanceof 이용한 연산결과로 true 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 의미함.

- 참조변수와 인스턴스의 연결

  • 멤버변수가 조상 클래스와 자손 클래스에 중복으로 정의된 경우, 조상타입의 참조변수를 사용했을 때는 조상 클래스에 선언된 멤버변수가 사용되고, 자손타입의 참조변수를 사용했을 때는 자손 클래스에 선언된 멤버변수가 사용된다.
  • 참조변수의 타입에 따라 결과가 달라지는 경우는 조상 클래스의 멤버변수와 같은 이름의 멤버변수를 자손 클래스에 중복해서 정의한 경우이다.

- 매개변수의 다형성

  • 매개변수가 Product타입의 참조변수라는 것은 메서드의 매개변수로 Product클래스의 자손타입의 참조변수면 어느 것이나 매개변수로 받을 수 있다는 뜻이다.

- 여러 종류의 객체를 배열로 다루기

  • 조상타입의 참조변수 배열을 사용하면, 공통의 조상을 가진 서로 다른 종류의 객체를 배열로 묶어서 다룰 있다.

 

class Buyer {
	int money = 1000;
    int bonusPoint = 0;
    Product[] item = new Product[10];
    int i = 0;
    
    void buy(Product p) {
    	if(money , p.price) {
        	System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
            return;
        }
        money -= p.price;
        bonusPoint += p.bonusPoint;
        intem[i++] = p;
        System.out.println(p + "을/를 구입하였습니다.");
    }
}

 

- Vector 메소드

  • 10개의 객체를 저장할 있는 vector인스턴스를 생성한다.
  • 10 이상의 인스턴스가 저장되면, 자동적으로 크기가 증가된다.

- 선언

 

Vector item = new Vector() ;

추상클래스 ( abstract class )

 

  • 추상클래스로 인스턴스를 생성할 없다.
  • 추상클래스는 상속을 받은 자손클래스에 의해서만 완성이 있다.
  • 추상클래스에도 생성자가 있으며, 멤버변수와 메서드도 가질 있다.

- 추상메서드

  • 선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 것이 추상메서드이다.
  • 상속받는 자손 클래스는 조상의 추상메서드를 상황에 맞게 적절히 구현해줘야 한다.
  • 'abstract' 앞에 붙여주고, 구현부가 없으니 {} 없다.

- 추상클래스의 작성

  • 추상화는 기존의 클래스의 공통부분을 뽑아내서 조상 클래스를 만드는 .
  • 추상메서드를 선언하는 이유는 자손 클래스에서 추상메서드를 반드시 구현하도록 강요한 .
  • 조상클래스가 추상메서드라도 자손이 상속을 받아 구현한 메서드를 사용이 가능함.

인터페이스(interface)

 

  • 추상클래스보다 추상화 정도가 높아서 추상클래스와 달리 몸통을 갖춘 일반 메서드 또는 멤버변수 구성원을 가질 없다. (추상클래스와 인터페이스의 차이점)
  • 추상메서드와 상수만 받을 있다.

- 인터페이스의 작성

interface 인터페이스이름{
	Public static final 타입 상수이름 = 값;
	Public abstract 메서드이름 (매개변수목록);

 

  • 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 있다.
  • 모든 메서드는 public abstract이어야 하며, 이를 생략할 있다.
  • Static default 제외.

- 인터페이스 상속

  • 인터페이스는 인터페이스로부터만 상속을 받을 있다.
  • 클래스와 달리 다중상속이 가능하다.

- 인터페이스 구현

  • Extends 대신 implements 사용한다.
  • 구현하는 인터페이스 메서드 일부만 구현한다면 abstract 붙여서 추상클래스로 구현 해야 한다.
  • 자손타입은 조상상속과 인터페이스 구현을 동시에 있다.
  • 인터페이스를 구현하는 클래스는 반드시 public으로 구현해야 한다.  (인터페이스가 public abstract 이기 때문)

- 인터페이스를 이용한 다중상속

  • 인터페이스는 static상수만 정의할 있으므로 조상클래스의 멤버변수와 충돌하는 경우는 거의 없다. (클래스에 이름을 붙여서 구별도 가능함.)
  • 메서드이름이 일치하여도 인터페이스는 추상이기 때문에 조상쪽 메서드를 상속 받으면 .
  • 다중상속 필요시 불러올 클래스 참조변수에 해당 인스턴스를 참조하여 사용할 ( 관계 - 포함 내용임.)

- 인터페이스를 이용한 다형성

  • 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조 있으며, 인터페이스 타입으로 형변환도 가능하다.

- 리턴타입

  • 리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미함.
Fightable method() {
	Fightable f = new Fightable();
    return f;
}

 

- 인터페이스의 장점

  • 개발시간을 단축
  • 표준화가 가능
  • 서로 관계없는 클래스들에게 관계를 맺어 있다.
  • 독립적인 프로그래밍이 가능하다.

- 인터페이스의 이해

  • 클래스를 사용하는 쪽과 클래스를 제공하는 쪽이 있다.
  • 메서드를 사용하는 쪽에서는 사용하려는 메서드의 선언부만 알면 된다.
  • 클래스 A 여전히 클래스 B 메서드를 호출하지만, 클래스 A 인터페이스 I하고만 직접적인 관계에 있기 때문에 클래스 B 변경에 영향을 받지 않는다.
  • 인스턴스 참조변수로도 Object 메서드를 호출 가능함.

 

 

- 디폴트 메서드와 static 메서드

  • 추상 메서드의 기본적인 구현을 제공하는 메서드
  • 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다.
  • 여러 인터페이스의 디폴트 메서드 간의 충돌
    • 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야 한다.
  • 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
    • 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

- 내부 클래스 

  • 클래스 안의 클래스 

 

class A {
	...
    class B {}
}

 

- 장점

  • 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근 있다.
  • 코드의 복잡성을 줄일 있다.(캡슐화)

 

class AAA {
	int i = 100;
    BBB b = new BBB();
    class BBB {
    	void method() {
        System.ote.println(i);
        }
    }
}

 

-  종류와 특징

내부 클래스 특징
인스턴스 클래스
(instance class)
외부 클래스의 멤버변수 선언위치에 선언. 외부 클래스의 인스턴스멤버 처럼 다루어진다. 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용될 목적으로 선언된다. 
스태틱 클래스
(static class)
외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 static멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static 메서드에서 사용될 목적으로 선언된다. 
지역 클래스
(local class)
외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다. 
익명 클래스 
(anonymous class)
클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스 (일회용)

 

- 접근제어자와 접근성

  • 내부 클래스의 제어자는 변수에 사용 가능한 제어자와 동일
  • Static 클래스만 static멤버를 정의 있다.
  • 예외로 instance local 내부 클래스에도 final상수에 static 붙일 있다.
class EX7_13 {
	class InstanceInner {}
    static class StaticInner {}
    
    InstanceInner iv = new InstanceInner();
    static StaticInner cv = new StaticInner();
    
    static void staticMethod() {
    	StaticInner obj2 = new StaticInner();
        Ex7_13 outer = new EX7_13();
        InstanceInner obj1 = outer.new InstanceInner();
    }
    void instanceMethod() {
    	InstanceInner obj1 = new InstanceInner();
        StaticInner obj2 = new StaticInner();
    }
    void method() {
    	class LocalInner{}
        LocalInner lv = new LocalInner();
    }
}

 

  • 내부클래스에서 외부 클래스의 private멤버도 접근가능하다.
  • 내부클래스에서 접근 가능한 지역변수는 외부 클래스에 final 붙은 상수만 접근가능하다.
  • 내부클래스 인스턴스를 생성하려면 외부클래스의 인스턴스를 생성 후에 사용해야함.
  • static 내부클래스는 바로 인스턴스 생성이 가능함.

'Language > Java' 카테고리의 다른 글

정규식(Regular Expression)  (0) 2023.03.25
(Java)10진법 <--> n집법 변환  (0) 2023.03.16
Chapter5. 배열(Array)  (0) 2022.12.03
Chapter4. 조건문과 반복문  (0) 2022.12.03
Chapter3. 연산자(Operator)  (0) 2022.12.03