본문 바로가기
코리아 IT아카데미/Java

8일차 | 배열, 배열리스트, 상속, 오버라이드, 상속할수없는클래스

by Sharon kim 2021. 10. 27.
chapter03 복습순서
메모
ch01>
ArrayMainTest
Marine,Zealot,Zergling 복사본
ArrayMainTest2
Book
ArrayMainTest3


ch02>
ArrayMainTest1
ch03>
MainTest1
MainTest2
MainTest3
Car
Engine
 

배열이란

package ch01;

public class ArrayMainTest {
	// START
	public static void main(String[] args) {

		// 배열
		// 배열이란 연관된 데이터를 모아서 통으로 관리하기 위해 사용하는 
		// 데이터 타입이다.
		// 변수가 하나의 데이터를 저장하기 위한 것이라면 
		// 배열은 여러 개의 데이터를 하나의 변수에 저장하기 위한 것
		// 이라고 할 수 있다.

		// 자바의 문법
		int number = 10;

		// 배열 선언 방법 2가지
		int[] arr1 = new int[3];// 1.을 권장
		int arr2[] = new int[10];// 2.
		
		
		//초기화 하는 방법 (값을 넣는 방법)
		arr1[0] = 33;
		arr1[1] = 10;
		arr1[2] = 11;
		// 모든 프로그램에서 index는 0부터 시작 : 
		// 크기(n)와 index의 마지막 번호(n-1)는 다르다.
		
		//배열 선언과 동시에 초기화
		int[] numbers1 = new int[] {11, 20, 30};//1.
		int[] numbers2 = {10, 50, 100};//2.
		
		//출력방법
		System.out.println(numbers1[0]);
		System.out.println(numbers1[1]);
		System.out.println(numbers1[2]);
		System.out.println(numbers1);
		
		// 
		String[] strArr = new String[10];
		strArr[0] = "야스오";
		strArr[1] = "티모";
		strArr[2] = "애쉬";
		strArr[3] = "다리우스";
		
		//1. 화면에 0,1,2,3,4 출력해주세요 단  for문 사용 금지
		System.out.println(strArr[0]);
		System.out.println(strArr[1]);
		System.out.println(strArr[2]);
		System.out.println(strArr[3]);
		
		// 배열은 클래스다 클래스는 쩜 연산자 사용 가능, 
		// 주소값이 담겼을 때는 쩜 연산자 사용가능
		System.out.println(strArr.length);
		
		System.out.println("==================");
		
		//코드 수정 null 값을 출력하지 마세요
		for(int i = 0; i < strArr.length; i++) {
			
			if(strArr[i] != null) {
				System.out.println(strArr[i]);	
			}//end of if
		}//end of for
			//me
//			if(i == 4) {
//				i -= 1;
//			}else {
//				System.out.println(strArr[i]);
//			}
//		}
		
		//모든 프로그래밍 언어에서는 index는 0부터 시작합니다.
		//배열을 사용할 때 보통 for문과 관계해서 많이 사용 합니다.
		
//		new int[22]; //길이 22, 21
//		new int[74]; //길이 74, 73
//		new int[283]; //길이 283, 282
		
	}// end of main
}// end of class

Marine,Zealot,Zergling 복사본

package ch01;

public class Zealot {

	private int power;
	private int hp;
	private String name;

	public Zealot(String name) {
		this.name = name;
		this.power = 10;
		this.hp = 100;
	}

	public void showInfo() {
		System.out.println("=====정보창=====");
		System.out.println("이름 : " + this.name);
		System.out.println("공격력 : " + this.power);
		System.out.println("체력 : " + this.hp);
		System.out.println("===============");
	}

	// 공격당합니다.
	public void beAttacked(int power) {
		this.hp -= power;
		if(this.hp <= 0) {
			System.out.println(this.name + "은  사망했습니다.");
			this.hp = 0;
		}
	}
	// 공격합니다. -> 질럿이 마린을 공격하는 동작
	// 다른 객체와 상호작용 - 메서드로 참조 변수 전달
	//getName
	public String getName() {
		return name;
	}
	
	//메서드 오버로딩을 사용해 보자
	public void attack(Marine marine){
		String targetName = marine.getName();
		System.out.println(this.name + "이 " + targetName +"을 공격");
		marine.beAttacked(this.power);
	}
	public void attack(Zergling zergling) {
		String targetName = zergling.getName();
		System.out.println(this.name + "이 " + targetName +"을 공격");
		zergling.beattacked(this.power);
	}

}// end

배열로 질럿 12마리 출력

package ch01;

public class ArrayMainTest2 {

	public static void main(String[] args) {
		// 연관된 데이터를 통으로 모아서 관리하기 위한 것
		int[] nums = new int[12];
		
		//질럿을 담을 수 있는 배열 12칸을 만들어 주세요
		Zealot[] zealots = new Zealot[12];
		//마린 
		Marine[] marines = new Marine[12];
		//저글링
		Zergling[] zerglings = new Zergling[12];
		
		//배열은 for문과 함께 많이 사용
		for(int i = 0; i < zealots.length; i++) {
			zealots[i] = new Zealot("질럿" + (i + 1));
		}//end of for
		
		//1. 마린 생성
		for(int i = 0; i < marines.length; i++) {
			marines[i] = new Marine("마린" + (i + 1));
		}
		//2. 저글링 생성
		for(int i = 0; i < zerglings.length; i++) {
			zerglings[i] = new Zergling("저글링" + (i + 1));
		}
		System.out.println(zealots[11].getName());
	
		//3. 질럿 12마리의 정보를 출력해 주세요 for문 사용
		for (int i = 0; i < zealots.length; i++) {
			zealots[i].showInfo();
		}
	}
}

Book 정보 담을 클래스 설계

package ch01;

public class Book {

	//멤버 변수
	int id;
	String title;
	String author;
	
	//생성자 멤버 3개를 입력 한번에 받는 생성자를  만들어 주세요
	
	public Book(int id, String title, String author) {
		this.id = id;
		this.title = title;
		this.author = author;
	}
	
	//메서드 만들어 주세요 showInfo();
	
	public void showInfo() {
		System.out.println("id : " + id);
		System.out.println("title : " + title);
		System.out.println("author : " + author);
	}
	
}//end of class

쇼핑카트에 책 담기 

package ch01;

import java.util.Calendar;

public class ArrayMainTest3 {
	//start
	public static void main(String[] args) {
		
		Book book1 = new Book(1, "흐르는 강물처럼","파울로 코엘료" );
		Book book2 = new Book(2, "플러터 UI실전","김근호" );
		Book book3 = new Book(3, "무궁화꽃이 피었습니다","김진명" );
		Book book4 = new Book(4, "리딩으로 리드하라","이지성" );
		Book book5 = new Book(5, "사피엔스","유발하라리" );
		
		//문제
		//1. 배열을 이용해서 shoppingCart 변수(배열)에 
		//객체를 담아 봅시다.
		Book[] shoppingCart = new Book[5]; 
		
		//2. 사고싶은 책 3개를 장바구니에 담아 봅시다.
		shoppingCart[0] = book1;
		shoppingCart[1] = book2;
		shoppingCart[2] = book3;
		
		//3. 장바구니에 담은 정보를 화면에 출력하세요.
		//오류 수정해 주세요
		
//		shoppingCart[0].showInfo();
//		shoppingCart[1].showInfo();
//		shoppingCart[2].showInfo();
		
//		for (int i = 0; i < shoppingCart.length; i++) {
//			if(shoppingCart[i] != null) {
//				shoppingCart[i].showInfo();
//			}
//		}
		//java.lang.NullPointerException 오류 이유 : 
		//shoppingCart[5] : 주소 | 주소 | 주소 | null | null
		//null도 다 나오라고 해서 그렇다.
		
		//4. 
		shoppingCart[0] = book5;
		
		//5. index 1번째에 book3을 추가 해주세요
		// 0, 1 = book3, 1->2 , 2->3, 3->4
		
		shoppingCart[0] = book1;
		shoppingCart[1] = book3;
		shoppingCart[2] = book2;
		shoppingCart[3] = book4;
		shoppingCart[4] = book5;
		
		//삭제 -> 배열에 담겨 있는 값을 제거 하려면 
		//3번째 인덱스를 지워보세요
		shoppingCart[3] = null;
		
		//배열에 추가를 하려면 직접 인덱스 연산을 해서 처리해야 한다.
		for (int i = 0; i < shoppingCart.length; i++) {
			if(shoppingCart[i] != null) {
				shoppingCart[i].showInfo();
		}
		
		}
	}//end of main

}//end of class

 


ArrayList 사용

package ch02;

import java.util.ArrayList;

import ch01.Book;

public class ArrayMainTest1 {

	public static void main(String[] args) {

		Book book1 = new Book(1, "흐르는 강물처럼", "파울로 코엘료");
		Book book2 = new Book(2, "플러터 UI실전", "김근호");
		Book book3 = new Book(3, "무궁화꽃이 피었습니다", "김진명");
		Book book4 = new Book(4, "리딩으로 리드하라", "이지성");
		Book book5 = new Book(5, "사피엔스", "유발하라리");

		// ArrayList 선언

		// 데이터를 담을 공간 만들기
		// !ArrayList는 배열과 달리 공간의 크기를 먼저 선언할 필요가 없다.
		ArrayList<Book> shoppingCart = new ArrayList<Book>();

		// 추가 방법 1 인덱스 >> 직접적으로 가공해야할 때 
			// 데이터를 추가하기
			shoppingCart.add(book1); // 0
			shoppingCart.add(book2); // 1
			shoppingCart.add(book3); // 2
			shoppingCart.add(book4); // 3
	
			System.out.println(shoppingCart.size());
			// 화면에 출력
			for (int i = 0; i < shoppingCart.size(); i++) {
				shoppingCart.get(i).showInfo();
			}
			
			System.out.println("=====================");
		
		// 추가 방법2 foreach >>단순하게 처음부터 끝까지 반복을 해야할 때
			shoppingCart.add(2, book5);
			// for문 2번째 방법  for ctrl + space => foreach
			for (Book b : shoppingCart) {
				b.showInfo();
			}
			System.out.println("=====================");		
		//삭제하기
			shoppingCart.remove(0);
			//foreach
			for (Book book : shoppingCart) {
				book.showInfo();
			}
			System.out.println("=====================");
			//전부 삭제
//			shoppingCart.clear();
			for (Book book : shoppingCart) {
				book.showInfo();
			}
			System.out.println("=====================");
		//수정하기
			shoppingCart.set(2, book1);
			//foreach문 생성해서 화면에 출력
			for (Book book : shoppingCart) {
				book.showInfo();
			}
		
			// C R U D -> 프로그래밍의 기본뼈대
			//create, read, update, delete
			
	}// end of main
}// end

상속이란 extends 

package ch03;

class A{
	int number1;
	int number2;
	int number3;
}
class B{
	int number1;
	int number2;
	int number3;
	int number4;
	int number5;
}
//상속
class C extends A{
	
	int number4;
	int number5;
}

public class MainTest1 {

	public static void main(String[] args) {
 //참조타입,참조변수 - > 주소값이 들어간다 -> 점연산자 사용가능
		C c = new C();
		c.number1 = 1;
		c.number2 = 2;
		c.number3 = 3;
		c.number4 = 4;
		c.number5 = 5;
		
		System.out.println(c.number1);
		System.out.println(c.number5);
		
	}//end
}//end

메서드 오버라이드 : 부모에 있는 메서드를 필요에 의해 재정의해서 사용

package ch03;

class Cal {
	
	public int sum(int n1, int n2) {
		return n1 + n2;
	}
	
	public int multiply(int n1, int n2) {
		
//		/*
//		 * 1000줄 ~~ 코드이다
//		 */
		return n1 * n2;
		//return super.multiply(n1, n2);
	}
}

class Cal2 extends Cal {
	public int minus(int n1, int n2) {
		return n1 - n2;
	}
	
	//메서드 오버로딩 :
	//이름은 같은데 매개변수는 다른
	//오버라이드 :
	//부모에 있는 메서드를 필요에 의해서 재정의 해서 사용하는 개념
//	public int multiply(int n1, int n2) {
//		if(n1 == 0 || n2 == 0) {
//			System.out.println("0을 입력 하지 마세요");
//		}
//		return n1 * n2;
//	}//똑같은 메서드 사용 가능

	@Override
	public int multiply(int n1, int n2) {
		if(n1 == 0 || n2 ==0) {
			System.out.println("multiply 메서드를 실행합니다.");
			return super.multiply(n1, n2);
		}
		//return super.multiply(n1, n2);
		//this.name = name;와 비슷
		return n1 * n2;
			  
	}
	
}//end of cal2 e cal

public class MainTest2 {

	public static void main(String[] args) {
		
		Cal2 cal2 = new Cal2();
		System.out.println(cal2.sum(5, 3));
		System.out.println(cal2.minus(10, 7));
		System.out.println(cal2.multiply(10, 0));
	}
}//end of MainTest2

Car, Engine 클래스 설계 : 의미 상 포함 관계가 아닌 둘은 상속할 수 없다.

자동차 정보 출력

package ch03;

public class MainTest3 {

	public static void main(String[] args) {
		
		// 자동차를 생성해서 showInfo 호출해주세요

		Car car1 = new Car("제네시스", 5500);
		car1.showInfo();
		
		//엔진의 정보를 출력해주세요
		car1.engine.showInfo();
		
	}//end
}//end

 

수업내용

[출처] https://blog.naver.com/devnote1 작성자 devnote1


배열이란?

 

배열(array)이란 연관된 데이터를 모아서 통으로 관리하기 위해서 사용하는 데이터 타입이다.

변수가 하나의 데이터를 저장하기 위한 것이라면 배열은 여러 개의 데이터를 하나의 변수에 저장하기 위한 것이라고

할 수 있다.

 

  • 동일한 자료형의 순차적 자료 구조
  • 인덱스 연산자[]를 이용하여 빠른 참조가 가능
  • 물리적 위치와 논리적 위치가 동일
  • 배열의 순서는 0부터 시작
  • 자바에서는 객체 배열을 구현한 ArrayList를 많이 활용함

 

배열 선언과 초기화

배열 선언하기

int[] arr1 = new int[10];
int arr2[] = new int[10];

 

배열 초기화 하기

  • 배열은 선언과 동시에 자료형에 따라 초기화 됨 (정수는 0, 실수는 0.0, 객체는 null)
  • 필요에 따라 초기값을 지정할 수 있음
int[] numbers = new int[] {10, 20, 30}; // 개수 생략해야 함
int[] numbers = {10, 20, 30}; // new int[] 생략 가능
int[] ids;
ids = new int[] {10, 20, 30}; // 선언 후 배열을 생성하는 경우는 new int[] 생략할 수 없음

 

배열 사용하기

[]인덱스 연산자 활용 - 배열 요소가 저장된 메모리의 위치를 연산하여 찾아 줌

배열을 이용하여 합을 구하기

int[] arr = new int[10];
int total = 0;

for(int i = 0, num = 1; i < arr.length; i++, num++){
	arr[i] = num;
}
for(int i = 0; i<arr.length; i++){
	total += arr[i];
}
System.out.println(total);

 

배열의 길이와 요소의 개수는 꼭 동일하지 않습니다.

  • 배열을 선언하면 개수만큼 메모리가 할당되지만, 실제 요소(데이터)가 없는 경우도 있음
  • 배열의 length 속성은 배열의 개수를 반환해주기 때문에 요소의 개수와는 다름
double[] dArr = new double[5];

dArr[0] = 1.1;
dArr[1] = 2.1;
dArr[2] = 3.1;

double mtotal = 1;
for(int i = 0; i <dArr.length; i++){
	mtotal *= dArr[i];
}
System.out.println(mtotal);

 

굳이 만들어 보자면 요소의 개수에 대한 변수(count)를 따로 유지

double[] dArr = new double[5];
int count = 0;
dArr[0] = 1.1; count++;
dArr[1] = 2.1; count++;
dArr[2] = 3.1; count++;

double mtotal = 1;
for(int i = 0; i < count; i++){
	mtotal *= dArr[i];
}
System.out.println(mtotal);

 

문자 배열을 만들어 A-Z까지 배열에 저장하고 이를 다시 출력하기

public class CharArrayTest{
	
    public static void main(string[] args){
    
    	char[] alpahbets = new char[26];
        char ch = 'A';
        
        for(int i = 0; i < alpahbets.length; i++){
        	
            alpahbets[i] = ch++;
        }
    	for(int i = 0; i < alpahbets.length; i++){
        
        	System.out.println(alpahbets[i] + "," + (int)alpahbets[i]);
        }
    }
}

 

향상된 for문 사용하기

배열의 n개 요소를 0부터 n-1까지 순차적으로 순회할 때 간단하게 사용할 수 있음

for(변수 : 배열){

}

public class CharArrayTest{

	public static void main(String[] args){
    
    	char[] alpahbets = new char[26];
        char ch = 'A';
        
        for(int i = 0; i < alpahbets.length; i++){
        
        	alpahbets[i] = ch++;
        }
    	for(char alpha : alpahbets){
        System.out.println(alpha +","+ (int)alpha);
        }
    }
}

 

객체 배열 사용하기

객체 배열 선언과 구현

기본 자료형 배열은 선언과 동시에 배열의 크기만큼의 메모리가 할당되지만, 객체 배열의 경우엔 요소가 되는 객체의

주소가 들어갈 메모리만 할당되고(null) 각 요소 객체는 생성하여 저장해야 함

 

Book.java

public class Book {
	
    private String title;
    private String author;
	
    public Book(){}
    
    public Book(String title, String author){
    	this.title = title;
        this.author = author;
    }
    
    public String getTitle(){
    	return title;
    }
    
    public void setTitle(String title){
    	this.title = title;
    }
    
    public String getAuthor(){
    	return author;
    }
    
   	public void setAuthor(String author){
    	this.author = author;
    }
    
    public void showBookInfo(){
    	System.out.println(title + "," +author);
    }
    
}//end of class book

 

BookArrayMainTest.java

public class BookArrayMainTest {
	public static void main(String[] args){
    	Book[] library = new Book[5];
        for(int i = 0; i < library.length; i++){
        	System.out.println(library[i]);
        }
    }
}

 

객체를 생성하여 각 배열의 요소로 저장하기

public class BookArrayTest {
	public static void main(String[] args){
    
    Book[] library = new Book[5];
    
    library[0] = new Book("태백산맥1", "조정래");
    library[1] = new Book("태백산맥2", "조정래");
    library[2] = new Book("태백산맥3", "조정래");
    library[3] = new Book("태백산맥4", "조정래");
    library[4] = new Book("태백산맥5", "조정래");
    
   	for(int i = 0; i < library.length; i++){
    	System.out.println(library[i]);
        library[i].showBookInfo();
    }
  }
}

 

객체배열 복사하기

▶System.arrayCopy(src, srcPos, dest, destPos, length) 자바에서 제공되는 배열 복사 메서드

 

얕은 복사

객체 주소만 복사되어 한쪽 배열의 요소를 수정하면 같이 수정됨

즉, 두 배열이 같은 객체를 가리킴

public class objectCopy{
	Book[] library = new Book[5];
    Book[] copyLibrary = new Book[5];
    
    library[0] = new Book("태백산맥1", "조정래");
    library[1] = new Book("태백산맥2", "조정래");
    library[2] = new Book("태백산맥3", "조정래");
    library[3] = new Book("태백산맥4", "조정래");
    library[4] = new Book("태백산맥5", "조정래");
    
    System.out.arraycopy(library, 0, copyLibrary, 0, 5);
    
    System.out.println("===========copy library==========")
    for( Book book : copyLibrary){
    	book.showBookInfo();
    }
    library[0].setTitle("나목");
    library[0].setAuthor("박완서");
		
		System.out.println("======library=========");
		for( Book book : library) {
			book.showBookInfo();
		}
		
		System.out.println("======copy library=========");
		
		for( Book book : copyLibaray) {
			book.showBookInfo();
		}
	}
}

 

깊은 복사

각각의 객체를 생성하여 그 객체의 값을 복사하여 배열이 서로 다른 객체를 가리키도록 함

public class ObjectCopy2 {

	public static void main(String[] args) {

		Book[] library = new Book[5];
		Book[] copyLibaray = new Book[5];
		
		library[0] = new Book("태백산맥1", "조정래");
		library[1] = new Book("태백산맥2", "조정래");
		library[2] = new Book("태백산맥3", "조정래");
		library[3] = new Book("태백산맥4", "조정래");
		library[4] = new Book("태백산맥5", "조정래");
		
		copyLibaray[0] = new Book();
		copyLibaray[1] = new Book();
		copyLibaray[2] = new Book();
		copyLibaray[3] = new Book();
		copyLibaray[4] = new Book();
		
		for(int i = 0; i< library.length; i++) {
			copyLibaray[i].setTitle(library[i].getTitle());
			copyLibaray[i].setAuthor(library[i].getAuthor());
		}
		
		
		library[0].setTitle("나목");
		library[0].setAuthor("박완서");
	
		System.out.println("======library=========");
		for( Book book : library) {
			book.showBookInfo();
		}
		
		System.out.println("======copy library=========");
		for( Book book : copyLibaray) {
			book.showBookInfo();
		}
	}
}

ArrayList

java.util 패키지에서 제공되는 ArrayList

  • 기존 배열 선언과 사용 방식은 배열의 길이를 정하고 요소의 개수가 배열의 길이보다 커지면 배열을 재할당하고 복사해야 했음 
  • 배열의 요소를 추가하거나 삭제하면 다른 요소들의 이동에 대한 구현을 해야함
  • ArrayList는 객체 배열을 좀 더 효율적으로 관리하기 위해 자바에서 제공해주는 클래스
  • 이미 많은 메서드들이 최적의 알고리즘으로 구현되어 있어 각 메서드의 사용 방법만 익히면 유용하게 사용할 수 있음

 

ArrayList의 주요 메서드

 

ArrayList를 활용한 간단한 예제

import java.util.ArrayList;

public class ArrayListTest {

	public static void main(String[] args) {

		ArrayList<Book> library = new ArrayList<Book>();
		library.add(new Book("태백산맥1", "조정래"));
		library.add(new Book("태백산맥2", "조정래"));
		library.add(new Book("태백산맥3", "조정래"));
		library.add(new Book("태백산맥4", "조정래"));
		library.add(new Book("태백산맥5", "조정래"));
		
		System.out.println(library.get(0).title);
		System.out.println(library.size());
		System.out.println(library.isEmpty());
		
		Book removeBook = library.remove(4);
		System.out.println(removeBook.title);
		System.out.println("===========");
		
		
		for(int i = 0; i < library.size(); i++) {
			library.get(i).showInfo();
		}
		
//		library.set(1, new Book("웹툰", "가나다"));
//		library.add(1, new Book("1111", "asdasdas"));

		
	}

}

상속

객체간의 상속은 어떤 의미일까?

클래스 상속

  • 새로운 클래스를 정의할 때 이미 구현된 클래스를 상속(inheritance) 받아서 속성이나 기능을 확장하여 클래스를 구현함
  • 이미 구현된 클래스보다 더 구체적인 기능을 가진 클래스를 구현해야 할 때 기존 클래스를 상속함

기능은 B클래스가 더 많다. 기능이 더많은 것이 자녀 클래스

  • 상속하는 클래스 : 상위 클래스, parent class, super class
  • 상속받는 클래스 : 하위 클래스, child class, subclass

 

상속을 구현하는 경우

  • 상위 클래스는 하위클래스보다 더 일반적인 개념과 기능을 가짐
  • 하위 클래스는 상위클래스보다 더 구체적인 개념과 기능을 가짐
  • 하위클래스가 상위클래스의 속성과 기능을 확장(extends)한다는 의미

상속을 활용한 멤버십 클래스 구현하기

회사에서 고객 정보를 활용한 맞춤 서비스를 하기 위해 일반고객(Customer)과 이보다 충성도가 높은 우수고객(VIPCustomer)에 따른 서비스를 제공하고자 함 물품을 구매 할때 적용되는 할인율과 적립되는 보너스 포인트의 비율이 다름 여러 멤버십에 대한 각각 다양한 서비스를 제공할 수 있음 멤버십에 대한 구현을 클래스 상속을 활용하여 구현해보기

 

public class Customer {

	private int customerID;
	private String customerName;
	private String customerGrade;
	int bonusPoint;
	double bonusRatio;
	
	public Customer() {
		customerGrade = "SILVER";
		bonusRatio = 0.01;
	}
	
	public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;
		return price;
	}
	
	public String showCustomerInfo() {
		return customerName + "님의 등급은 " + customerGrade + 
				"이며, 보너스 포인트는" + bonusPoint + "입니다";
		
	}
}

 

우수 고객(VIPCustomer) 구현

매출에 더 많은 기여를 하는 단골 고객 보너스 포인트는 제품 가격의 5%를 적립해 줌 담당 전문 상담원이 배정됨

● Customer 클래스에 추가해서 구현하는 것은 좋지 않음
● VIPCustomer 클래스를 따로 구현
● 이미 Customer에 구현된 내용이 중복되므로 Customer를 확장하여 구현함(상속)
public class VIPCustomer extends Customer{

	private int agentID;
	double salesRatio;
	
	public VIPCustomer() {
		customerGrade = "VIP";    //오류 발생
		bonusRatio = 0.05;
		salesRatio = 0.1;
	}
	
	public int getAgentID() {
		return agentID;
	}
}

 

protected 접근 제어자

● 상위 클래스에 선언된 private 멤버 변수는 하위 클래스에서 접근 할 수 없음

● 외부 클래스는 접근 할 수 없지만, 하위 클래스는 접근 할 수 있도록 protected 접근 제어자를 사용

 

Customer.java

protected int customerID;
	protected String customerName;
	protected String customerGrade;

	//getter, setter 구현
	...
	public int getCustomerID() {
		return customerID;
	}

	public void setCustomerID(int customerID) {
		this.customerID = customerID;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	public String getCustomerGrade() {
		return customerGrade;
	}

	public void setCustomerGrade(String customerGrade) {
		this.customerGrade = customerGrade;
	}

 

Customer와 VIPCustomer 테스트하기

public class CustomerTest {

	public static void main(String[] args) {
		Customer customerLee = new Customer();
		customerLee.setCustomerName("이순신");
		customerLee.setCustomerID(10010);
		customerLee.bonusPoint = 1000;
		System.out.println(customerLee.showCustomerInfo());
			
			
		VIPCustomer customerKim = new VIPCustomer();
		customerKim.setCustomerName("김유신");
		customerKim.setCustomerID(10020);
		customerKim.bonusPoint = 10000;
		System.out.println(customerKim.showCustomerInfo());
	}
}

 

상속에서 클래스 생성 과정과 형 변환

하위 클래스가 생성 되는 과정

● 하위 클래스를 생성하면 상위 클래스가 먼저 생성 됨

● new VIPCustomer()를 호출하면 Customer()가 먼저 호출 됨

● 클래스가 상속 받은 경우 하위 클래스의 생성자에서는 반드시 상위 클래스의 생성자를 호출 함

 

Customer.java

public Customer() {
		customerGrade = "SILVER";
		bonusRatio = 0.01;
		
		System.out.println("Customer() 생성자 호출");
}

 

VIPCustomer.java

public VIPCustomer() {
		customerGrade = "VIP";
		bonusRatio = 0.05;
		salesRatio = 0.1;
		
		System.out.println("VIPCustomer() 생성자 호출");
}

 

super 키워드

● 하위 클래스에서 가지는 상위 클래스에 대한 참조 값

● super()는 상위 클래스의 기본 생성자를 호출 함

● 하위 클래스에서 명시적으로 상위 클래스의 생성자를 호출하지 않으면 super()가 호출 됨

( 이때 반드시 상위 클래스의 기본 생성자가 존재 해야 함)

● 상위 클래스의 기본 생성자가 없는 경우 ( 다른 생성자가 있는 경우 ) 하위 클래스에서는 생성자에서는 super를 이용하여 명시적으로 상위 클래스의 생성자를 호출 함

● super는 생성된 상위 클래스 인스턴스의 참조 값을 가지므로 super를 이용하여 상위 클래스의 메서드나 멤버 변수에 접근할 수 있음

 

Customer.java

// 디폴트 생성자 없애고 매개 변수가 있는 생성자 추가
public Customer(int customerID, String customerName) {
		this.customerID = customerID;
		this.customerName = customerName;
		
		customerGrade = "SILVER";
		bonusRatio = 0.01;
		System.out.println("Customer(int, String) 생성자 호출");
}

 

VIPCustomer.java

// super를 이용하여 상위 클래스의 생성자 명시적으로 호출
public VIPCustomer(int customerID, String customerName) {
		super(customerID, customerName);
		
		customerGrade = "VIP";
		bonusRatio = 0.05;
		salesRatio = 0.1;
		
		System.out.println("VIPCustomer(int, String) 생성자 호출");
}

 

CustomerTest.java

public class CustomerTest {

	public static void main(String[] args) {
		
		Customer customerLee = new Customer(10010, "이순신");
		customerLee.bonusPoint = 1000;
		System.out.println(customerLee.showCustomerInfo());
		
		VIPCustomer customerKim = new VIPCustomer(10020, "김유신");
		customerKim.bonusPoint = 10000;
		System.out.println(customerKim.showCustomerInfo());
	}
}

 

상속에서 인스턴스 메모리의 상태

● 항상 상위 클래스의 인스턴스가 먼저 생성되고, 하위 클래스의 인스턴스가 생성 됨

형 변환(업캐스팅)

● 상위 클래스로 변수를 선언하고 하위 클래스의 생성자로 인스턴스를 생성

● Customer customerLee = new VIPCustomer();

● 상위 클래스 타입의 변수에 하위 클래스 변수가 대입

VIPCustomer vCustomer = new VIPCustomer();

addCustomer(vCustomer);

int addCustomer(Customer customer){ }

● 하위 클래스는 상위 클래스의 타입을 내포하고 있으므로 상위 클래스로의 묵시적 형 변환이 가능함

● 상속 관계에서 모든 하위 클래스는 상위 클래스로 형 변환(업캐스팅)이 됨

( 그 역은 성립하지 않음)

형 변환과 메모리

● Customer vc = new VIPCustomer(); 에서 vc가 가리키는 것은?

● VIPCustomer() 생성자에 의해 VIPCustomer 클래스의 모든 멤버 변수에 대한 메모리는 생성되었지만,

변수의 타입이 Customer 이므로 실제 접근 가능한 변수나 메서드는 Customer의 변수와 메서드임

 

메서드 재정의하기(overring)

 

하위 클래스에서 메서드 재정의 하기

● 오버라이딩(overriding) : 상위 클래스에 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않는 경우 하위 클래스에서 동일한 이름의 메서드를 재정의 할 수 있음

● VIPCustomer 클래스의 calcPrice()는 할인율이 적용되지 않음

● 재정의 하여 구현해야 함

VIPCustomer.java

@Override
public int calcPrice(int price) {
	bonusPoint += price * bonusRatio;
	return price - (int)(price * salesRatio);
}

 

@overriding 어노테이션 (annotation)

● 애노테이션은 원래 주석이라는 의미

● 컴파일러에게 특별한 정보를 제공해주는 역할

● @overriding 애노테이션은 재정의 된 메서드라는 의미로 선언부가 기존의 메서드와 다른 경우 에러가 남

형 변환과 오버라이딩 메서드 호출

Customer vc = new VIPCustomer();

vc 변수의 타입은 Customer지만 인스턴스의 타입은 VIPCustomer 임

자바에서는 항상 인스턴스의 메서드가 호출 됨

CustomerTest.java

public class CustomerTest {

	public static void main(String[] args) {
		
        Customer customerLee = new Customer(10010, "이순신");
		customerLee.bonusPoint = 1000;
		System.out.println(customerLee.showCustomerInfo());
		
		VIPCustomer customerKim = new VIPCustomer(10020, "김유신");
		customerKim.bonusPoint = 10000;
		System.out.println(customerKim.showCustomerInfo());
		
		int priceLee = customerLee.calcPrice(10000);
		int priceKim = customerKim.calcPrice(10000);
		
		System.out.println(customerLee.showCustomerInfo() 
        + " 지불금액은 " + priceLee + "원 입니다.");
		System.out.println(customerKim.showCustomerInfo() 
        + " 지불금액은 " + priceKim + "원 입니다.");
		
		Customer customerNo = new VIPCustomer(10030, "나몰라");
		customerNo.bonusPoint = 10000;
		int priceNo = customerNo.calcPrice(10000);
		System.out.println(customerNo.showCustomerInfo() + " 지불금액은 " 
        + priceNo  + "원 입니다.");

	}
}