프로그래밍/- java

class ,객체,메소드,생성자,상속,super , 추상, interface

즐겁게 하하하 2022. 2. 3. 08:29
728x90
★ 가비지 컬렉터 :: 사용하지 않는 불필요한 메모리를 회수하는 청소부
★ class(설계도) 
    => 객체를 생성하기 위해사용 ( 제품 만들려고 ) 
         => 인스턴스화 => 
               인스턴스(삼성 TV) ,  인스턴스(LG TV)
                   => 객체가 가진 속성(변수)과 기능(메서드)를 사용하기 위해  

★ 메서드 :: 기능( 크기, 높이 색상.. )

Class Tv {  // TV인스턴스
    boolean power; // 변수( 속성 )
    void power(){ power = !power; }  // 메서드
}
## ===================================================================
★ class 이름은 대소문자를 구분한다.public class 는 없어도 된다. 
★ 하나의 소스 파일에는 하나의 public class 만 가능
★ 소스 파일 이름 != public class 이름 => 에러

★ 소스 파일 이름과 같은 class 안에 Main이 있어야 실행이 된다.
class Hello2 {  // 파일명 Hello2.java
    public static void main(String[] args){ }
}
 
강제로 > Main class 를 지정하여 실행시킬 수도 있다.

★ 인스턴스(객체) 참조
  ⓐ TV t; //참조변수 선언  
  ⓐ t = new TV(); // 인스턴스 생성 :: 생성자TV
  ⓑ TV t = new TV();
## ======================================
  ⓐ TV[] arr = new TV[3];  // 객체 배열
  arr[0] = new TV(); // 필수
  arr[1] = new TV();
  arr[2] = new TV();

  ⓑ TV[] arr = { new TV() ,  new TV() ,  new TV() }  //초기화 
## ======================================
★ 배열 변수 선언( 복습 )
    int[] aa = new int[] {1,2,3,4,5};
	int[] bb = {1,2,3,4};
	int[] cc = new int[3];
## ======================================
★ 변수 => 배열(같은 타입) => 클래스
class Variables{  // 선언문만 가능한 class 영역
  int iv;        // 인스턴스 변수( 인스턴스가 생성될때 생성 , 객체 생성 필요 )
  static int cv; // 클래스 변수( static, 공유변수, 객체 생성 필요없음 )
  void method(){ // 메소드 정의( 하나의 메서드는 하나의 기능만 하도록 한다. )
      int lv = 0;  //지역변수( 변수 선언문이 수행 되었을때 )
  }
}
 
 

★ 호출 스택 :: 메서드 수행에 필요한 메모리가 제공되는 공간 
                메서드가 호출되면 스택에 메모리 할당, 종료시 해제
★ 기본형 매개변수 ( readonly )
   void change( int x ){}

★ 참조형 매개변수 ( read , write ) 
  Date2 d = new Date2();
  change(d);
  static void change( Date2 d ){ d.x = 1000 }

★ 참조형 반환타입
  => 아래 캡쳐 참조.
## ======================================static 메소드 / 인스턴스 메소드 
   static   : A1.method(); // 객체 만들지 않고 호출 가능
   인스턴스 : A1 d1 = new A1();  d1.method();

   static : 메소드 내에서 인스턴스 변수(iv) X
   인스턴스 : 메소드 내에서 인스턴스 변수(iv) O
## ======================================
★ 접근 제어자  
   public : 제한없다.
   protected : 같은 패키지 내, 다른 패키지의 자손 클래스 에서 접근 가능
   (default)  : 같은 패키지 내에서만 접근이 가능하다.
   private  : 같은 클래스 내에서만 접근 가능
## ======================================final :: 마지막의, 변경될 수 없는
   final class FinalTest {
     final int max_size = 10 // 값 변경 불가능(상수)
     final void getMaxSize(){ // 오버 라이딩 불가
        final int lv = max_size; // 값 변경 불가능(상수)
     }
   } // 조상이 될 수 없는 클래스
## ======================================
 
참조형 매개변수
static 메소드 안에서 static 변수, 메소드만 사용 가능하다.
 

★ 오버로딩 : 기존에 없는 새로운 메서드를 정의

int add( int a , int b){}   
int add( int a , long b){} 
long add( long a , long b){} 
int add( int a , int b , int c ){}
int add( int[] a ){}
___________________________________________________________
★ 오버 라이딩 ( 덮어쓰다 ) : 상속받은 메소드의 내용을 변경

   => 선언부 변경 불가 , 선언부가 조상 클래스의 메소드와 일치해야 한다.
   => 내용만 변경 가능
   => 접근 제어자( public , private )을 조상보다 좁은 범위로 할 수 없다.
   => 예외 선언시 조상의 메소드 보다 많이 선언 할 수 없다.
      class Parent { void parentMethod() throw IOException , SQLException {} }
      class Child extends Parent { void parentMethod() throw IOException {} }

★ 생성자  
   => 모든클래스는 하나의 생성자를 반드시 가져야 한다.
   => 생성자의 경우 항상 반환값이 없어서 void를 안쓴다.
   => 생성자가 하나도 없을때만 컴파일러가 기본생성자를 자동으로 생성한다.    
 
생성자에서 다른 생성자 호출은 첫줄에서만 가능하다.

★ 상속 class Child extends Parent {}
   자손은 모든 맴버를 상속받음 ( 생성자 , 초기화블럭 제외 )
   자손의 맴버 개수는 조상보다 같거나 많다.
   자손의 변경은 조상과 관계없다.
  
   java는 단일 상속만을 허용한다. class TvDVD extends TV , DVD {  // XX 오류
    => 따라서 비중이 높은 하나의 클래스만 상속하고 나머지는 포함 관계로 한다.
       class TvDVD extends TV  {  DVD dvd = new DVD(); }  
    => 부모가 없는 clsss는 자동으로 objcet 클래스(컴파일러 자동추가)를 상속받는다.
       Object 클래스(조상클래스) 에 정의된 11개의 메소드를 상속받는다.
       toString(); / equals() / hashCode()  등 
       class TV extends Object { }
    => 생성자의 첫줄엔 반드시 생성자를 호출해야 한다.
       Parent ( int x , int y ) { super(); // object() }
       Child ( int x , int y , int z ) { 
             super(); this.x = x; this.y = y; this.z = z; 
       }
## ======================================
★ Super 
  super.x  :  조상의 맴버를 자신의 맴버와 구분할때 이용 
  조상의 생성자를 호출 할 때 사용
  조상의 맴버는 조상의 생성자를 호출해서 초기화 super()
상속 관계 / 포함 관계
인스턴스 변수 this 변수가 없어서 super값을 불러옴(좌측)

★ 패키지
  .jar 은 클래스들을 압축한 파일 ( JDK 설치경로\jre\lib 에 위치 )

★ import 패키지명.클래스명
   패키지와 클래스 선언 사이에 위치한다.
   import java.util.*

★ (static) :: import static 패키지명.클래스명 
   import static java.lang.Math.random; (클래스 이름을 생략할 수 있게 해준다.)
   system.out.println( Math.random() ); => system.out.println( random() )   

★ 다형성
  => 참조 변수와 인스턴스 타입이 일치 
    SmartTv s = new SmartTv();  
    조상과 자손의 참조 변수 모두 사용가능

  => 참조 변수와 인스턴스 타입이 불일치( 조상 타입 참조 변수로 자손 타입 인스턴스 참조 가능 )
     Tv   t = new SmartTv();  // (조상::리모컨) t = new (자손::기능) (OK)    
                              // (자손)   t = new 조상 (Error)
    조상의 참조 변수만 사용 가능  

  => 참조 변수의 형변환( 상속 관계일때만 가능 )
     사용할 수 있는 맴버의 갯수를 조절하는것
     조상, 자손 관계의 참조변수는 서로 형변환 가능
  
  => instanceof 연산자
    참조변수의 형변환 가능여부 확인 ( 가능하면 true 반환 )
     void doWork( FireEngine fe ){
       if( fe instanceof Car ){   // Car c = (Car) fe   :: true ??
           Car c = (Car) fe
           c.water();
       }
     }
     
 FireEngine fe = new FireEngine();
 Car ca = new Car();
 System.out.println( fe instance of Object );     //true :: Object obj = (Object) fe;
 System.out.println( fe instance of Car );        //true :: Car c = (Car) fe;
 System.out.println( ca instance of FireEngine ); //fale :: FireEngine fe = (FireEngine) ca

★ abstract :: 추상적인 , 미완성의
   => abstract 리턴타입 메서드 이름();
   => 추상 메서드 :: {} 구현부가 없는 메서드.
   => 추상 클래스 :: 추상메서드를 가지고 있는 클래스
   => 추상클래스를 상속받는 하위클래스는 
      반드시 abstract 메서드를 오버라이딩 해야된다. => 강제성

   => 추상클래스는 인스턴스 생성 불가( 미완성 설계도 )
      Player p = new Player(); ( x ) // 인스턴스 생성 불가

   => 추상클래스를 상속받아서 완전한 클래스를 만든후에 사용
     abstract class Player { // 추상 클래스
        abstract void play();  // 추상 메소드 :: 구현부가 없는 메소드
        abstract void stop(); 
     }

     abstract class AbstractPlayer extends Player { 
        void play();  // 모두 구현하지 않은경우 class에 abstract 붙여야 한다.
     }

     class AudioPlayer extends Player { // 추상클래스 상속받아 사용.
        void play() {/* 내용 */} 
        void stop() {/* 내용 */}  // 모두 구현되면 abstract 안붙여도 된다.
     }

     AudioPlayer ap = new AudioPlayer(); // 사용 가능
     Player ap = new AudioPlayer();   // 다형성
     
     
    /** ============ 참조 변수의 형 변환 ============ */
    package ch001;
    abstract class Player { 
        abstract void play( int pos );
        abstract void stop();	
    }
    //추상 클래스는 상속을 통해 객체 생성
    class AudioPlayer extends Player{
        void play(int pos) {System.out.println( pos + " 위치부터 play 합니다.");}
        void stop() {System.out.println("종료합니다.");}
    }

    public class Hello1 {
        public static void main(String[] args) {
            //Player p = new Player();// 추상클래스 인스턴스 생성 불가

        /**  묵시적 형변환 *************
         * 상위(부모) 클래스 타입 = 하위(자식) 클래스 타입 
         * 부모타입은 자식타입을 포함
         * 자신 클래스에 정의된 변수와 메소드만 사용이 가능
         * 단, 하위클래스에서 오버라이딩 했을 경우 하위클래스에 선언된 메소드가 호출
         * *************************/
            Player ap = new AudioPlayer(); // 다형성
            ap.play( 100 );
            ap.stop();

            AudioPlayer ap2 = new AudioPlayer();  
            Player pl = (Player) ap2; // (Player) 생략가능
            pl.play( 200 );
            pl.stop();

        /**  명시적 형변환 *************
         * 하위클래스 타입 = (하위클래스타입) 상위 클래스 타입 
         * 부모의 클래스가 묵시적 형변환이 되어 있어야 한다. 
         * Player ap3 = new AudioPlayer();  
         * *************************/				
            Player ap3 = new AudioPlayer(); //묵시적 형변환
            AudioPlayer pl2 = (AudioPlayer) ap3; //명시적 형변환
            pl2.play( 300 );
            pl2.stop();	
        }
    }
 
class Product2 {
	int price;			// 제품의 가격
	int bonusPoint;	// 제품구매 시 제공하는 보너스점수

    Product2() {} // 기본 생성자
	Product2(int price) {
		this.price = price;
		bonusPoint = (int)(price/10.0);
	}	
}

class Tv2 extends Product2 {
	Tv2() {  super(100);	 }
	public String toString() { return "Tv"; }
}

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

class Audio2 extends Product2 {
	Audio2() { super(50); }
	public String toString() { return "Audio"; }
}

class Buyer2 {			  // 고객, 물건을 사는 사람
	int money = 1000;	  // 소유금액
	int bonusPoint = 0; // 보너스점수
	Product2[] cart = new Product2[10];   // 구입한 제품을 저장하기 위한 배열
	int i =0;			  // Product배열에 사용될 카운터

	void buy(Product2 p) {
		if(money < p.price) {
			System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
			return;
		}

		money -= p.price;             // 가진 돈에서 구입한 제품의 가격을 뺀다.
		bonusPoint += p.bonusPoint;   // 제품의 보너스 점수를 추가한다.
		cart[i++] = p;                // 제품을 Product[] cart에 저장한다.
		System.out.println(p + "을/를 구입하셨습니다.");
	}

	void summary() {	              // 구매한 물품에 대한 정보를 요약해서 보여 준다.
		int sum = 0;                 // 구입한 물품의 가격합계
		String itemList ="";         // 구입한 물품목록

		// 반복문을 이용해서 구입한 물품의 총 가격과 목록을 만든다.
		for(int i=0; i<cart.length;i++) {
			if(cart[i]==null) break;
			sum += cart[i].price;
			itemList += cart[i] + ", ";
		}
		System.out.println("구입하신 물품의 총금액은 " + sum + "만원입니다.");
		System.out.println("구입하신 제품은 " + itemList + "입니다.");
	}
}

class Ex7_9 {
	public static void main(String args[]) {
		Buyer2 b = new Buyer2();
		b.buy(new Tv2());
		b.buy(new Computer2());
		b.buy(new Audio2());
		b.summary();
	}
}
package ch001;
abstract class Unit { 
	int x , y;
	abstract void move( int x , int y );  // 구현부{} 없는경우 abstract 붙여야함.
	void stop() {}
}

class Marine extends Unit{
	void move(int x , int y) { System.out.println("마린 이동"); }
	void stimPack() {}
}

class Tank extends Unit{
	void move(int x , int y) { System.out.println("Tank 이동"); }
	void changeMode() {}
}

class Dropship extends Unit{
	void move(int x , int y) { System.out.println("드랍쉽 이동"); }
	void load() {}
	void unload() {}
}

public class Hello {
	public static void main(String[] args) {

//		Unit[] group = new Unit[3];
//		group[0] = new Marine();
//		group[1] = new Tank();
//		group[2] = new Dropship();
		Unit[] group = { new Marine() , new Tank() , new Dropship() };
		
		for (int i = 0; i < group.length; i++) {
			group[i].move(100 , 200);
		}	
	}
}

★ 인터페이스( 구현된게 없는 설계도 )
   => 추상 메서드의 집합 이고 모두 public 
   => default 메서드 추가 가능( 추가된 기능 )
   => static 메서드 추가 가능( 추가된 기능 )
   => 인터페이스 조상은 인터페이스만 가능( object가 최고 조상 아님 )     
      interface abcInterface{
         public static final int name = 1; // 변하지 않는 수(상수) 가능
         public abstract String method();   // public abstract 생략 가능
      }

   => 다중 상속 가능 :: interface C extends A , B {}  // 총돌해도 관계X
   => 구현 
      :: class C implements A , B { /* 추상 메소드 모두 구현 */ }
      :: abstract class C implements A , B { /* 추상 메소드 일부만 구현 */ }
      :: class C extends B implements A {} // B 상속받고 , A 인터페이스를 구현하는 C

   => 매개변수가 인터페이스 :: 인터페이스를 구현한 클래스의 인스턴스만 가능하다. 
   => return 타입이 인터페이스 :: 인터페이스를 구현한 클래스의 인스턴스 반환

★ 인터페이스 장점
   =>  두 객체 간의 중간역할
   =>  선언과 구현을 분리시킴( 구현부분이 바뀌어도 선언부분에 영향이 없음 )
   =>  표준화가 가능하다.
   =>  변경에 유리한 설계가 가능하다.
   =>  서로 관계없는 클래들을 관계를 맺어 줄 수 있다.
interface A { // 인터페이스
	public abstract String move( int a ); // public abstract 생략가능
}

interface B extends A { // A 인터페이스 상속 받은 B 인터페이스
	void move2( int a );
    public static final int abc = 10;	// 인터페이스는 상수(변하지 않는 수) 가능
}

class C implements B { // B 인터페이스 구현하는 C 클래스 
	public String move( int a ) { /* 내용 */  return "";  }
	public void move2(int a){ /* 내용 */ }  
}
//=================================================================================
abstract class D { 
	int x , y;
	abstract void move( int x , int y ); // 구현부{} 없는경우 abstract 붙여야함.
	void stop() {}
}

class E extends D { // 추상클래스 구현
    int x , y;
	void move( int x , int y ) { /* 내용 */ }
	void stop() { /* 내용 */ }
}

// 추상클래스와 인터페이스 공통점
  => 추상 메서드를 가지고 있다.
  => 구현된 것이 전혀 없다.
// 추상클래스와 인터페이스 차이점
  => 인터페이스는 iv( 인스턴스 변수)를 가질 수 없다.

 

 

서로 관계없는 클래들을 관계를 맺어 줄 수 있다.
★ 함수형 인터페이스
 => 애너테이션 @Functionallnterface :: 컴퍼일러가 올바르게 작성했는지 체크해줌
 => 하나의 추상 메서드만 가져야 한다는 제약이 있다.
 

 

 

 

 

728x90