본문 바로가기

코딩공부일지/자바독학

[자바혼공] 객체지향 후반부

  • 자료출처

생활코딩 by egoing - 자바: https://opentutorials.org/module/516

남궁석의 자바의정석: https://github.com/castello/javajungsuk_basic/


1. 상속

- 기존 클래스를 재사용하여 새로운 클래스를 작성하는 것

- 상속을 통한 클래스 작성 시 적은 양의 코드로 새로운 클래스 작성 가능

- 코드 공통 관리 가능

- 코드의 재사용성을 높이고, 코드의 중복 제거 - > 프로그램 생산성, 유지보수에 기여

class Parent {}                  // Parent: 조상 클래스
class Child extends Parent {
}                                // Child: 자손 클래스

- 자손 클래스는 조상 클래스의 모든 멤버를 상속받음

-자손 클래스의 멤버 개수는 조상 클래스보다 항상 많거나 같음

2. 클래스 간의 관계 - 포함관계

 class Point {
       int x;
       int y;
 }
 
 
 class Circle {
     Point c = new point();
     int r;
 }

3. Object 클래스 - 모든 클래스의 조상

- 모든 클래스 상속계층도의 최상위에 있는 조상클래스

- 다른 클래스로부터 상속 받지 않는 모든 클래스들은 자동적으로 Object 클래스로부터 상속받음

 class TV { // extends object가 자동 추가
 }

4. 오버라이딩

1) 오버라이딩이란?

- 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것

class Point {
   int x;
   int y;
   
   String getLocation() {
      return x, y;
    }
 }
 
class Point3D extends Point {
   int z;
   
   String getLocaton () {            // 오버라이딩
      return x, y, x;
      }
 }

-  자손 클래스가 자신에 맞게 메서드 내용을 변경해야할 때, 조상의 메서드를 오버라이딩 함

2) 오버라이딩의 조건:

1] 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없음
2] 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없음
3] 예외는 조상클래스보다 더 많이 선언할 수 없음

5. 참조변수 super

-  자손클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수

 - 상속받은 멤버와 자신의 멤버 이름이 같을 때 super 을 붙여서 구별

6. super() - 조상의 생성자

- 조상의 생성자를 호출하는데 사용

7. 패키지

- 클래스의 묶음, 서로 관련된 클래스들끼리 그룹 단위로 묶음으로써 클래스를 효율적으로 관리할 수 있음

-같은 이름의 클래스라도 서로 다른 패키지에 존재O, 같은 이름의 클래스도 서로 다른 패키지에 속해있다면 패키지명으로 구분이 가능

- 패키지의 선언

package 패키지명;

 - 패키지 선언문은 주석, 공백을 제외한 첫 번재 문장이어야 하며, 하나의 소스파일에 한 번만 선언 가능

- 클래스명과 구분을 위해 소문자로 하는 것을 원칙

- 소스파일 패키지 미지정시 자동으로 unnamed package에 속하게 됨

8. 클래스 패스 (class path)

- JVM이 프로그램을 실행할 때, 클래스파일을 찾는 데 기준이 되는 파일 경로

9. import문 

- 자신과 동일한 패키지에 존재하는 클래스가 아닌, 다른 패키지의 클래스는 클래스명만으로 접근이 불가능하며, 반드시 패키지명을 포함하여야 접근 가능 --> 매번 패키지명을 붙여서 코드를 작성하는 것은 귀찮음

 ----> 해당 패키지명을 import 문으로 등록시키면 클래스명만으로 사용이 가능해짐

- 특정 패키지 or 패키지 내의 클레스를 현재 클레스 내에 포함시킬 때 사용

 - 컴파일러에게 소스파일에 사용된 클래스의 패키지 정보 제공

 - 컴파일 시 컴파일러는 import 문을 통해 소스파일에 사용된 클래스들의 패키지를 알아낸 다음, 모든 클래스 앞에 패키지명을 붙여줌

 - 자동 import문 추가: ctr+shift+o

- 클래스의 코드 작성 전 import 문으로 사용하고자 하는 클래스 패키지를 미리 명시하면 패키지명은 생략 가능

package 문 => import 문 => class 선언문

- 선언방법

import 패키지명.클래스명;
or 
import 패키지명.*;         --> 같은 패키지의 여러 클래스가 사용될 때

- static import 문: static멤버 호출 시 클래스 이름 생략가능

10. 제어자 

- 클래스, 변수, 메서드의 선언부에 함께 사용되어 부가적인 의미 부여

접근제어자: public, protected, default, private
그 외 제어자: static, final, abstract, native, transient, synchronized, volatile, strictfp

- 하나의 대상에 대해 여러 제어자 조합 사용 가능 but 접근제어자는 하나만 선택가능

1) 접근제어자

제어자 같은클래스 같은패키지 자손클래스  전체
public O O O O
protected O O O (다른패키지지만
자손인 경우)
 
(default)//제어자없음 O O    
private O      

- 클래스 내부에 선언된 데이터를 보호하기 위해 사용, 외부에서 변경하지 못하도록 외부로부터의 접근 제한

-클래스 내에서만 사용되는 내부 작업을 위해 임시로 사용되는 멤버변수나 부분작업을 정리하기 위한 메서드 드으이 멤버들을 클래스 내부에 감추기 위하여 사용

==> data hiding, 객체지향개념의 "캡슐화"에 해당

2) 기타제어자

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

- 인스턴스 변수는 하나의 클래스로부터 생성되었더라도 각기 다른 값 유지, 클래스 변수는 인스턴스에 관계없이 같은 값

- static이 붙으면 인스턴스가 아닌 클래스와 관계된 것이기 때문에 인스턴스를 생성하지 않고 사용 가능

static 멤버변수 - 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 됨
- 클래스변수는 인스턴스를 생성하지 않고 사용 가능
- 클래스가 메모리에 로드될 때 생성
메서드 - 인스턴스를 생성하지 않고 호출 가능한 static 메서드가 됨
- static 메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없음

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

final 클래스 변경 불가한 클래스, 확장할 수 없는 클래스가 됨
메서드 변경 불가한 메서드, 오버라이딩을 통한 재정의 볼가
멤버변수 변수 앞에 final이 붙으면 값을 변경할 수 없는 상수가 됨
지역변수

(3) abstract - 추상의, 미완성의

- 메서드 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언하는데 사용

abstract 클래스  클래스 내에 추상 메서드가 선언되어 있음을 의미
메서드  선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알림
abstract class AbstractTest { 
  abstract void move();
 
}

 

11. 다형성

- 여러가지 형태를 가질 수 있는 능력

- 자바에서는 한 타입의 참조변수로 여러 타입의 객체 참조 가능

- 조상클래스 타입의 참조변수로 자손 클래스의 인스턴스 참조 가능  (반대의 경우는 불가능)

class Tv {
  boolean power;
  int channel;
  
  void power()         { power = !power;}
  void channelUp()     { ++channel;   }
  void channelDown()   { --channel;   }
}

class SmartTv extends Tv {
    String text;
    void caption() {
}


 Tv t= new Tv();
 SmartTv s=new SmartTv();
 
 Tv t= new SmartTv(); ---> 조상타입의 참조변수(리모콘)으로 자손 인스턴스 참조

 

12. 참조변수의 형변환

- 서로 상속관계에 있는 클래스 사이에서만 가능

(자손타입-> 조상타입, 조상타입-> 자손타입)

class Car {}
class FireEngine extends Car {}
class Ambulance extends Car {}

FireEngine f = new FireEngine();

Car c = (Car) f;  // 자손타입->조상타입의 Car로 형변환, 생략가능
FireEngine f2 = (FireEngine) c // 자손타입의 FireEngine으로 형변환, 생략불가

- 참조변수의 형변환은 리모콘(참조변수)를 다른 종류의 것으로 바꾸는 

- 사용할 수 있는 멤버개수를 조절하기 위해서

- 자손->조상타입 형변환 시: 다룰 수 있는 멤버의 개수가 줄어들기 때문에 항상 안전, 따라서 생략가능

- 조상->자손타입 형변환시: 다룰 수 있는 멤버의 개수가 늘어나기 때문에 생략불가

class Ex7_7 {
  public static void main(String args[])
  Car car = null;
  FireEngine fe = new FireEngine();
  FireEngine fe2 = null;
  
  fe.water();
  car = fe;            // car = (Car) fe; 형변환 생략
  car.water();        // 컴파일 에러, Car타입 참조변수로 water()호출 불가
  
  
  fe2 = (FireEngine)car; // 자손타입 참조변수로 조상타입 가리킴, 형변환 생략불가
  fe2.water();
  }
}


class Car {
   String color;
   int door;
   
   void drive() {
      System.out.println("drive,");
   void stop() {
      System.out.println("stop!!!")
   }
 }
 
class FireEngine extends Car {
   void water() {
      System.out.println("water!!!");
   }
}

 

13. instanceof 연산자

- 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 사용

- 주로 조건문에서 사용

- [참조변수] instanceof [타입(클래스명)]

- 연산결과 - boolean값인 true / false 반환 

   ==> 연산결과 true시 참조변수가 검사한 타입으로 형변환 가능함을 의미

 void doWork(Car c) {
   if (c instanceof FireEngine){
        FireEngine fe = (fireEngine)c;
        fe.water();
        ......

 

14. 매개변수의 다형성

class Product {
   int price;
   int bounsPoint;
}
class Tv extends Product{}
class Computer extedns Product{}

class Buyer {
   int money = 1000;
   int bounusPoint = 0;
  
  
    void buy(Tv t) { 
       money = money - t.price;
       bonusPoint = bonusPoint + t.bonusPoint;
     }
  }

====> buy 메서드로는 Tv 타입밖에 구매할 수 없음, 현 시점 다른 물건을 구매하려면 다른 제품도 구입할 수 있는 추가 메서드 필요

 void buy(Computer c){
    money = money - c.price
    bonusPoint = bonusPoint + c.bonusPoint;
 }

===> 매서드에 다형성 적용시 하나의 매서드로 처리 가능

class Product {
   int price;
   int bounsPoint;
}
class Tv extends Product{}
class Computer extends Product{}

class Buyer {
   int money = 1000;
   int bounusPoint = 0;
  
  
    void buy(Product p) { 
       money -= p.price;
       bonusPoint += p.bonusPoint;
     }
  }

==> 매개변수를 Product 타입의 참조변수로 사용시, Product 클래스의 자손타입 참조변수면 어느 것이나 매개변수로 사용 가능, 향후 제품class 추가시 Product클래스를 상속받기만 하면 매서드 매개변수로 사용 가능

15. 추상클래스 / 추상매서드

1) 추상클래스

: 미완성 매서드(abstract매서드)를 포함하는 클래스

- 추상클래스 자체로를 클래스 역할을 할 수 없지만, 새 클래스 작성 시 바탕이 되는 조상 클래스로서의 의미

- 클래스 앞 "abstract"만 붙이면 됨

- 생성자,멤버변수, 메서드 가질 수 있음

abstract class 클래스명 {
...
}

2) 추상메서드

: 메서드의 선언부, 구현부 중 선언부만 작성하고 구현부는 작성하지 않고 남겨둔 메서드 (미완성메서드)

- 메서드의 내용이 상속받는 클래스에 따라 달라질 수 있으므로 선언부만 작성,

  주석을 덧붙여 기능 수행 목적을 알려주고, 실제 내용은 상속받는 클래스에서 구현하도록 비워둠

- 구현부가 없으므로 {} 대신 ; 기입

/ 주석에 어떤 기능을 수행할 목적으로 작성하였는지 기입 / 
abstract 리턴타입 메서드이름();
abstract class Player {
      abstract void play (intpos);            // 추상매서드
      abstract void stop ();                  // 추상매서드
 } 
 
 class AudioPlayer extends Player {
     void play(intpos){}   // 추상매서드 구현
     void stop() {}        // 추상메서드 구현
 }
 
 abstract class AbstractPlayer extends Player {
      void play(intpos) {}   // 추상메서드 구현
}

 

 

16. 인터페이스

1) 인터페이스란

: 일종의 추상클래스, 추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높아 몸통을 갖춘 일반 메서드 or 멤버번수를 구성원으로 가질 수 없음. only 추상메서드, 상수만 멤버로 가질 수 있음

- 추상클래스가 부분적으로 완성된 '미완성 설계도'라면, 인터페이스는 구현된 것은 아무것도 없고 밑그림만 있는 '기본설계도'

- 그 자체로 사용되지 않고 다른 클래스 작성에 도움 줄 목적으로 작성

- class 대신 "interface" 사용 / 접근제어자 public, default만 가능

interface 인터페이스이름 {
  public static final 타입 상수이름 = 값;
  public abstract 메서드명(매개변수목록);
  
}
- 모든 멤버변수는 public static final 이어야 하며, 생략 가능
- 모든 메서드는 public abstract 이어야 하며, 생략 가능

2) 인터페이스의 상속

- 인터페이스간의 상속만 가능하며, 클래스와 달리 다중상속이 가능함

- 인터페이스는 class 와 달리 Object와 같은 최고 조상이 없음

interface Movable {
  /* 지정된 위치(x ,y)로 이동하는 메서드 */
  void move(int x, int y);
}

interface Attackable {
   /* 지정된 대상(u)를 공격하는 기능의 메서드*/
    void attact(Unit u);
 }
 
 interface fightable extends Movable, Attackable {}
  // 다중상속 가능, 
  // fightable 자체는 정의된 멤버가 없지만 조상 인터페이스로부터 상속받은 두 개의 추상메서드를 멤버로 가짐

3) 인터페이스 구현(implement)

- 그 자체로는 인스턴스를 생성할 수 없으며, 자신에게 정의된 추상메서드의 몸통을 만들어주는 클래스 작성 필요

- extends를 사용하지 않고 implement를 사용함

class 클래스명 implements 인터페이스명 {
}
class Fighter implements Fightable {
    public void move(int x, int y)
    public void attack(Unit u)
}

- 상속과 구현 동시 가능

class Fighter extends Unit implements Fightable

4) 인터페이스를 이용한 다형성

- 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스 참조 가능

- 인터페이스 타입으로 형변환도 가능

- 인터페이스는 메서드의 매개변수 타입으로 사용될 수 있음

- 리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미

5) 인터페이스의 장점

1. 개발시간 단축 가능
2. 표준화 가능
3. 서로 관계없는 클래스들 사이에 관계를 맺어줄 수 있음
4. 독립적인 프로그래밍 가능

 

17. 디폴트 메서드와 static 메서드

- 원래는 인터페이스에 추상 메서드 선언만 가능하였으나 JDK1.8부터 디폴트 메서드와 static메서드 추가가 가능해짐

- 디폴트 메서드: 추상메서드의 기본적인 구현을 제공하는 메서드로, 추상메서드가 아니기 때문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 됨 

interface MyInterface {
   void method();
   default void newMethod(){}
}

 

18. 내부클래스 (???)

1) 내부클래스의 선언

- 클래스 내에 선언된 클래스, 서로 긴밀한 관계에 있는 클래스를 내부클래스로 넣을 수 있음

- 내부클래스는 외부클래스를 제외하고 다른 클래스에서 잘 사용되지 않는 것이어야 함 

장점
-내부 클래스에서 외부 클래스 멤버에 쉽게 접근 가능
-코드의 복잡성 줄일 수 있음(캡슐화)

- 내부클래스의 종류와 특징: 변수의 선언위치에 따른 종류와 같음

(유효범위 및 접근성)

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

2) 내부클래스의 제어자와 접근성

-외부클래스의 멤버변수와 같은 위치에 선언되며, 멤버변수와 같은 ㅓㅅㅇ질을 가짐

- 내부클래스가 외부클래스의 멤버와 같이 간주되고, 인스턴스멤버와 static멤버 간의 규칙이 내부 클래스에도 똑같이 적용됨

 

19. 익명 클래스  (??)

-클래스의 선언과 객체의 생성을 동시에 하는 클래스

-단 한 번만 사용 가능하며, 오직 하나의 객체만 생성가능한 일회용클래스