gi_dor

[Java] CH7 객체지향 개념 본문

First/Java

[Java] CH7 객체지향 개념

기돌 2023. 3. 20. 17:29

 

2023.03.20
[7장 -  객체지향 프로그래밍Ⅱ]

1. 상속 


1 ) 기존의 클래스로 새로운 클래스를 작성 ( 코드의 재사용)
2 ) 두 클래스를 부모와 자식으로 관계를 맺어줌
3 ) 자손은 조상의 모든 멤버를 상속 받는다 ( 생성자 , 초기화 블럭 x ) ▶ 자손의 멤버개수는 항상 조상 보다 많거나 같다!
4 ) 자손 변경은 조상에 영향을 미치지 않느다 

작성방법 : class 자식클래스 extends 조상 클래스 {   }

 

2. 포함 

1 ) 클래스의 멤버로 참조 변수를 선언
2 ) 작은 단위의 클래스를 만들고  조합해서 큰단위의 클래스를 생성함
3 ) 클래스 간의 관계 결정방법
  ① 상속 : ~은 ~ 이다.  is - a    // Ex ) Circle 은 Point 이다   원은 점이다
  ② 포함 : ~은 ~ 을 가지고 있다 has - a  //  Ex )  Circle 은 Point를 가지고 있다  원은 점을 가지고 있다
 

3 . 단일 상속

1 ) Java는 단일 상속만 허용한다
2 ) 다중 상속 효과를 내는방법 : 비중이 높은 클래스는 상속으로 , 나머지는 포함 관계로

겉으로는 TVCR 의 메서드를 호출,  내부적으로는 VCR객체 생성후 VCR메서드 호출

 

4. Object 클래스 

1 ) 최상위 클래스 , 모든 클래스의 조상
2 ) 조상이 없는 클래스는 Object 클래스를 자동적으로 상속받음 
  ▶ 11개의 메서드  , toString () ,  .equals() ...etc

5. 오버라이딩

1 ) 상속받은 메서드의 내용을 변경 
2 ) 조건 :  조상과 선언부가 일치 해야한다
① 접근제어자는 조상의 메서드 보다 좁게 변경이 불가
② 조상보다 많은 예외부 불가
③ 인스턴스 메서드를 static 메서드로 또는 반대로 변경불가

6 . 오버라이딩 , 오버로딩

✔ 오버라이딩 : 부모로부터 상속받은 메서드의 내용을 변경
✔ 오버로딩 : 같은 이름의 새로운 메서드를 생성

7. super - 참조변수

1 ) 객체 자신을 가르키는 참조 변수 ( 조상과 자신의 멤버를 구별하기 위해 쓰임 )
2 ) 인스턴스 메서드 , 생성자 내에서만 존재함
this.x -> 자손클래스에 선언된 x
super.x ->  조상으로부터 상속받은 x

8. super ( ) - 조상 클래스의 생성자


1 ) 조상의 멤버를 초기화 하기위한 생성자
2 ) Object 클래스를 제외한 모든 클래스의 생성자는
    첫줄에 반드시 자신의 다른 생성자 또는 조상의 생성자를 호출 해야함
     * 그렇지 않으면 컴파일러가 자동으로 super( )  삽입함.

9. package

1 ) package ?

▪  서로 관련된 클래스의 묶음 (끼리끼리 모여있는 클래스들 묶음)
▪ 클래스의 실제 이름은 패키지를 포함

패키지 - 폴더
하위패키지 - 하위 폴더
클래스 - 클래스 파일

2 )  패키지 선언

package 패키지이름 ;

▪ 패키지는 소스 파일의 첫번째 문장으로 딱 한번만 선언
▪ 같은 소스파일의 클래스들은 모두 같은 패키지에 속한다
▪ 패키지 선언이 없다면 이름 없는 패키지에 속하게된다

3 ) 클래스 패스 (환경변수) : 클래스파일(*class) 위치를 알려주는 경로 (path)
  ; 로 경로간 구분한다 

10. import 문

1 ) 컴파일러에게 클래스가 속한 패키지를 알림
2 ) 작성방법 :  import  패키지이름.클래스이름;  (단축키 : ctrl + shift + o)
  ① package 문
  ② import 문
  ③ class 선언
* static import 입력시 클래스 이름 없이 static 멤버 호출 가능
* import 패키지이름. 클래스이름 ;
*  import  패키지이름.*;  이용해 패키지에 속하는 모든 클래스를 패키지명 없이 사용 할수 있음

import java.util.Scanner;
import java.util.ArrayList;
import java.util.Date;

import java.util.*;

 

static import문 
* static 멤버 ( cv , static 메서드 ) 사용 할 때  클래스 이름 생략해줌

 import static java.lang.Integer ;    
 import static java.lang.Math.random;
 import static java.lang.System.out;
 
 // out.println(.random);

 


1. 제어자

클래스 , 클래스멤버 (메서드 ,멤버변수)에 부가적인 의미를 부여

* 접근제어자 : public , protected , (default) , private
* 그외 제어자 : static , final , abstract      ( 나머지는 다음기회에 배우자 )
하나의 대상에 여러 제어를 같이 사용이 가능함 , 접근제어자는 4가지중 1가지만 쓸수 있음
접근 제어자를 가장 왼쪽으로 두고 사용

1 ) static  - 공통적인
static은 멤머변수 , 메서드 , 초기화 블럭에서 사용 (객체 생성없이 사용)
static 메서드 내에서는 인스턴스 멤버들을 사용 할수 없음 

2 ) final - 변경될수 없는

final 은 어디에든 붙일수 있으며 붙이는 위치에 따라 기능이 달라진다
1️⃣ 클래스 : 변경 , 확장 불가능한 클래스 
                   상속계층도에서 가장 마지막
                   자손이 없는 클래스 = 다른 클래스의 조상이 될수 없음 

2️⃣ 변수 (iv , lv )  : 상수 

3️⃣ 메서드 : 오버라이딩이 불가능한 메서드
                   + 오버 라이딩 ? 조상으로부터 상속받은 메서드의 내용을 변경

3 ) abstract - 미완성의


1️⃣ 클래스 : 클래스 안에 추상메서드가 존재하고 있다는 뜻 ( 미완성 설계도 )

2️⃣ 메서드 : 선언부만 있고 구현부인  {  } 가 존재 하지 않는 메서드

3️⃣ abstrct 클래스는 객체를 생성할수 없다, 추상 메서드를 가지고 있으니 상속을 받아서 완성 해줘야 한다

2.  접근제어자

  같은 클래스 같은 패키지 같은 패키지 
+
자손클래스

제한 없음
public
protected  
(default)    
private      

접근범위 : public > protected > (default) > private

4 ) 캡슐화와 접근제어자 

 

3. 다형성 

조상타입 참조변수로 자손타입 객체를 참조할수 있음
반대로 자손타입의 참조변수로 조상타입의 객체를 참조 할수는 없다.

참조변수가 사용할수 있는 멤버의 개수는 인스턴스의 멤버개수보다 적거나 같아야 한다.
참조변수 타입과 인스턴스 타입은 보통 일치하지만 때때로 일치하지 않을수 있다.

class Tv { }

class SmartTv extends Tv { }


Tv t = new Tv ();
SmartTv stv = new SmartTv ();
// 기존에 우리가 쓰던
// 참조변수와 인스턴스의 타입이 일치


Tv t = new SmartTv () ;
//  조상타입 참조변수로 자손타입 인스턴스 참조 
// Tv타입 참조변수 t로 SmartTv인스턴스의 모든 멤버를 사용할수 없음
// Tv 클래스로부터 상속받은 멤버만 사용 할수 있다.


SmartTc stv = new Tv ();  
// 자손타입 참조변수로 자상타입 객체 참조 할수 없음.

 

4. 참조변수의 형변환 

아직도 헷갈림 추후 참조변수 형변환 공부 해야함 아직도 이해 못했음 23.04.07

 

5. instanceof 연산자

instanceof 연사자를 통해 참조변수의 형변환이 가능한지 확인


1️⃣ instanceof 연산자 사용 , 형변환가능 여부 확인
2️⃣ 형변환
3️⃣ instanceof 의 왼쪽에는 참조변수 , 오른쪽에는 타입 ( 클래스 ) 연산결과로 boolean 값인 true ,false로 반환
      (+ 20230407 )

FireEngine fe = new FireEngine();

System.out.println(fe instanceof Object);
 Object obj = (Object) f;
 
 System.out.println(fe instanceof Car);
 Car car = (Car) fe;


참조 변수의 형변환은 왜 하는가? 
▶ 참조변수를 변경함으로 써 사용할수 있는 멤버 갯수를 조절하기위해

6. 매개변수의 다형성

참조형 매개변수로 메서드를 호출시 '자신과 같은타입' 또는 ' 자손타입의 인스턴스 ' 를 넘겨줄수 있음

class Product{
	int price;
	int bonuspoint;
	Product(){}
	Product(int price){
		this.price = price;
		bonuspoint = (int)(price/10.0);
			}
	}

class Tv extends Product {
	Tv() {
		super(100);		// super 는 조상클래스의 생성자를 호출함  상속받은거 초기화 하려고
						// 
	}
	public String toString() {	
	return "Tv";				 
	}
}


class Computer extends Product {
	Computer(){
		super(200);
	}
	public String toString() {
		return "Computer";
	}
}


class Keyboard extends Product{
	Keyboard(){
		super (30);
	}
	public String toString() {
		return "Keyboard";
	}
}


class Buyer{
	int money = 1000;
	int bonuspoint = 0;
      // buyer클래스 money - Product p   
	  // product p는 객체 자손타입 , 자기자신 다 다룰수있음
	  // product 참조변수가 매개변수면 자손타입 참조변수 아무거나 매개변수로 쓸수있음 
	  
	void buy(Product p) {
		if(money < p.price ) { // 보유 금액보다 제품가격이 비싸다면
		System.out.println("잔액이 부족해 제품을 구매 할수 없습니다");
		return ;	
			}
	
	  money = money - p.price;
	  bonuspoint = bonuspoint+ p.bonuspoint;
	  System.out.println("제품 "+ p+ " 을/를 구매하셨습니다");
		}
}
public class day230326_01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
	
		
		Buyer b = new Buyer();
		
		Product p = new Tv();
		
		Keyboard k = new Keyboard();
		Computer c = new Computer();
		Tv t = new Tv();
		
		b.buy(p);
		//	b.buy(new Tv());
		System.out.println("가격은 "+ t.price +" 만원 입니다");
		System.out.println("현재 남은 돈은 "+b.money+" 만원 입니다");
		System.out.println("현재 보너스 점수는 "+ b.bonuspoint+" 점 입니다");
		System.out.println();
		
		b.buy(new Keyboard());
		System.out.println("가격은 "+ k.price +" 만원 입니다");
		System.out.println("현재 남은 돈은 "+b.money+" 만원 입니다");
		System.out.println("현재 보너스 점수는 "+ b.bonuspoint+" 점 입니다");
		System.out.println();
		
		b.buy(new Computer());
		System.out.println("가격은 "+c.price+ " 만원 입니다");
		System.out.println("현재 남은 돈은 "+b.money+" 만원 입니다");
		System.out.println("현재 보너스 점수는 "+ b.bonuspoint+" 점 입니다");
			
	}

}

 

 

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

1 ) 조상타입 배열에 자손타입의 객체를 담을수 있다


2 ) 묶어서 다르고 싶은 객체들의 상손관계를 따져서 가장 가까운 공통조상 클래스 타입의 참조변수 배열을 생성해서 
객체들을 저장

Product [] p = new Product[3];

p[0] = new Tv();
p[1] = new Computer();
p[2] = new Keyboard();

Product2 [] cart = new Product2 [10]; 
//  구입한 제품을 저장하기위한 배열

int i = 0;
cart[i++] = p;

// cart[0] 부터 1씩 증가해서 
// 제품을 Product2[] cart 에 저장함

 


1. 추상클래스

미완성 설계도 , 미완성 클래스
▶  미완성 메서드를 갖고 있는 클래스

객체 생성불가 
✔ 왜 ?  메서드가 완성형이 아닌 미완성

1️⃣ 미완성 메서드를 갖고 있어서 추상 클래스 일 뿐 그외 멤버인 멤버변수 , 메서드를 가질수 있다
2️⃣ 상속을 통해서 자손에서 완성시켜 객체를 생성

// 기본에 우리가 쓰던 클래스
class Car { }

// 추상 클래스
abstract class Car { }

2. 추상메서드

메서드는 선언부 + 구현부로 이루어져 있다
추상 메서드는 선언부는 존재하되 구현부 {  } , 몸통이 존재 하지 않음

✔ 왜 사용하는가 ? 꼭 필요하지만 자손마다 다르게 구현되어야 할 때

abstract class Car { 
 	abstract void drive();  // {  } 몸통 없이 ; 으로 끝남
    abstract void stop();
    }

3. 추상메서드의 구현

abstract class Car {
	abstract void play (int pos);
    abstract void stop();
    }
    
    // 추상클래스의 추상메서드 구현 !
    // 어떻게 ? 상속을 통해서
    
    class Audi extends Car{
    	void play(int pos) { 
            System.out.println("출발 합니당");
            }
            
        void stop () {
        System.out.println("멈춰 !");
          	}
            
        }
        
    abstract Audi extedns Car {
    	void play(int pos) { 
          	  System.out.println("출발 합니당");
            	}
            }
            
         // 추상메서드 2개중 1개만 구현 했기 때문에 
         // 클래스 앞에 abstract 제어자 붙음
         // 구현은 했지만 덜 구현해서 여전히 미완성 클래스

 

4.인터페이스

일종의 추상클래스 , 밑 그림만 그려져있는 '기본 설계도'

1 ) 모든 메서드 : public abstract 메서드이름   //  public abstract 생략가능
2 ) 모든 멤버변수 : public static final , 상수    // 생략가능
3 ) 자체적으로 객체 생성불가 

interface PlayCard{
 	public static final int SPADE = 4;	// 상수는 대문자
    final int DIAMOND =3; 	// public static final int DIAMOND =3;
    static int HEART = 2; 	// public static final int HEART = 2;
    int CLOVER =1; 	// public static final int CLOVER = 1;
    
    public abstract String getCartdNumber();
    String getCardKind();	// public abstract String getCardKind();
    }

 

abstract class 와 interface 차이점
  • 추상 클래스 : 추상메서드 외에  , 멤버변수 , 생성자 , 메서드를 가지고 있음 
  • 인터페이스 : 추상메서드와 상수만 멤버로 가질수 있음
interface A {	// class 대신 interface 사용
	public static final int a = 3;
    // final int a = 3; 
    
    public abstract void abc();
    // void abc();
    }

 

5. 인터페이스 상속

인터페이스는 인터페이스 한테 상속받을수 있으며 다중상속이 가능 하다

interface A {
	void move(int x, int y);
    }
    
    interface B {
    void attack();
    void shield();
    }
    
    interface Knight extends A,B {
    void fireball();
   // void attack();	// 상속받은 멤버들
   // void shield();
   // void move(int x, int y);
   
   
   }

 

6. 인터페이스의 구현

인터페이스는 추상클래스와 마찬가지로 자체적으로 객체 생성불가
추상클래스는 상속을 통해 추상메서드를 완성해서 객체를 생성
인터페이스는 구현을 통해 추상메서드를 완성해서 객체를 생성

7. 인터페이스를 이용한 다형성

인터페이스는 구현클래스의  부모 일까 ?

class Fight extends Unit implements Fightale{
	public void move (int x, int y) { }
    public void attack ( Fightable f) {  }
    
    }
    
    // Unit 을 상속받은 Fiht
    // Fightable 구현한 Fight
    
    Unit u = new Fight();
    // 조상클래스   =  자손객체
    
    Fightale f = new Fight();
    // 인터페이스 = 자손객체
    
   // Fightable에 정의된 멤버메서드만 사용가능 
  //  interface Fightavle {
  // void move( int x, int y);
  //  void attack(Fightable f);
  //  }
  
  f.move(200,10);
  f.attack(new Fighter());

 

인터페이스를 메서드의 매개변수로 사용가능
매개변수로 인터페이스를 사용한다면 , 해당 인터페이스를 구현한 쿨래스의 객체만 가능함!!


인터페이스를 메서드의 리턴타입으로 지정할수 있다
인터페이스 Fightable 을 구현한 클래스의 객체를 반환

Fightable method() {  // return 타입을 Fightable 인터페이스로
...
Fight f = new Fight();
return f;  //  Fight
// return new Fight();
}

 

8. 인터페이스의 장점Ⅰ

1 ) 두 대상(객체) 간의 연결 , 대화 , 소통을 돕는 중간역할을 한다
알맹이가 바뀌어도 껍데기가 그대로 라면 사용에 지장이없음 (변경에 유리함)

2 ) 선언(설계)과 구현을 분리 시킬수 있게한다
변경사항이 있어도 수정 범위가 적다
알맹이 - 껍데기 분리 시킴 (변경에 유연함)

3 ) 인터페이스 덕분에 B가 변경되어도 A는 안바꿀수있음 ( 느슨한 결합)

// 직접적인 관계의 클래스 (A - B) 

class A {
public void methodA(B b){
	b.methodB();	// B클래스의 메서드를 호출
    }
  } 
  
  class B {
  pulbic void methodB()}
  		System.out.println("methodB()");
        }
     }
     
class Interface{
  	Public static void main (String args[]) }
    	A a = new A();
        a.methodA(new B() );
        }
  }  
      
// 간적적인 관계의 두 클래스
      
class A {
  public void methodA(I i ){
   i.methodB();
      }
   }
   
Interface I {
   void methodB() ;
   }
      
class B implements I {
    public void methodB() {
     System.out.println("methodB();" );
      }
 }

 

9. 인터페이스의 장점 

  • 개발 시간 단축  
  • 변경에 유리한 설계가 가능함
  • 표준화가 가능함
  • 서로 관계없는 클래스들을 관계를 맺어줄수 있다

728x90

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

[Java] CH8 예외처리  (0) 2023.04.02
[Java] 6장 QUIZ  (0) 2023.03.21
[Java] CH6 객체지향 개념  (0) 2023.03.13
[Java] CH5 배열  (0) 2023.01.15
[Java] CH4 조건문과 반복문  (0) 2023.01.11