웹_프론트_백엔드/JAVA프레임윅기반_풀스택

2020.03.24

shine94 2020. 3. 24. 08:57

1. 자바 클래스 구성

   class 클래스 이름 {
          Fields 필드
           : 멤버변수(member variables), 속성(attribute) 이라고도 함

     
          Constructors 생성자

           : 객체 생성시 호출됨, new 연산자 뒤에 붙는 것이 바로 생성자 
             필드 초기화

      
          Methods 메소드
           : 멤버메소드(member method) 혹은 동작(behavior) 라고도 함

             객체의 동작 정의
   }

 

 

2. 클래스 만들면서 상속 설정하는 법

 : Superclass에 상속 받을 클래스를 선택 후 생성

 

[실습코드]

 

1. [과제] 정규표현식을 이용한 쿠폰 판정식

** RegExp04Main

package com.lec.java.regexp04;
/* 정규표현식 연습
 * 
 * 이번에 우리 쇼핑몰에서 할인 쿠폰을 발행하려 한다.
 * 발행되는 쿠폰의 일련번호 형식은 다음과 같다.
 * 
 *    알파벳두자리-숫자4자리-숫자3자리-알파벳3자리 
 * 
 * 알파벳은 대소문자 구문 없슴
 * 숫자는 0으로 시작하면 안됨.
 * 사용자는 발급받은 쿠폰번호를 입력해야 하는데, 
 * 위와 같은 형식만 받아들일수 있도록 만들자
 * 
 * 허용예]
 * 	Ab-7890-786-zuy
 * 	ki-2010-893-Zip
 * 
 * 불가]
 * 	xX-1200-089-zuy
 * 	p9-324-089-zopl
 * 
 *  쿠폰번호를 계속해서 입력 받으면서 
 * "유효한 쿠폰입니다"  혹은 "유효한 쿠폰이 아닙니다" 판정결과를 출력
 * 
 * 'quit' 입력하면 프로그램 종료
 * 
 */
public class RegExp04Main {

	public static void main(String[] args) {
		System.out.println("정규표현식 예제");
		System.out.println("쿠폰 판정식");
		
		RegExp04Method method = new RegExp04Method();
		method.view();
		
		System.out.println("프로그램 종료");
	} // end main
	
} // end class

 

** RegExp04Method

package com.lec.java.regexp04;

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

// Ctrl + Shift + F : 이클립스 자동 들여쓰기 맞춤
public class RegExp04Method {

	// method name: view
	// return: void
	// arguments: 없음
	// 기능 : 화면 출력
	void view() {
		Scanner sc = new Scanner(System.in);

		// 쿠폰 번호 저장할 변수
		String coupon;

		// 1) 2자리-4자리-3자리-3자리
		String regex1 = "^..-....-...-...$";

		// 2) 알파벳두자리-숫자4자리-숫자3자리-알파벳3자리
		// 알파벳은 대소문자 구문 없슴
		// 숫자는 0으로 시작하면 안됨
		String regex2 = "^[a-zA-Z][a-zA-Z]-[1-9][0-9][0-9][0-9]-[1-9][0-9][0-9]-[a-zA-Z][a-zA-Z][a-zA-Z]$";

		while (true) {
			// 쿠폰번호를 계속해서 입력 받으면서
			System.out.print("쿠폰 번호를 입력하세요(종료 quit 입력) : ");
			coupon = inputChoice(sc);

			// 'quit' 입력하면 프로그램 종료
			if (coupon.equals("quit")) {
				break;
			}

			// 1) 2자리-4자리-3자리-3자리 조건에 충족하는지 확인하기
			if (couponJudge(regex1, coupon)) {
				// 1 조건이 충족하면 2 조건 판정결과 출력
				if (couponJudge(regex2, coupon)) {
					System.out.println("유효한 쿠폰입니다.");
				} else {
					System.out.println("유효한 쿠폰이 아닙니다.");
				}
			} else {
				System.out.println("2자리-4자리-3자리-3자리 조건에 충족하지 않습니다.");
			}
            
		} // end while()
        
	} // end view

	// method name: inputChoice
	// return: String
	// arguments: Scanner sc (입력장치)
	public static String inputChoice(Scanner sc) {
		// 쿠폰번호 입력받기
		// [허용] Ab-7890-786-zuy ki-2010-893-Zip [불가] xX-1200-089-zuy p9-324-089-zopl
		// coupon = "p9-324-089-zopl";
		String coupon = sc.nextLine();

		// 사용자에게 입력 받은 쿠폰정보 메인으로 돌려주기
		return coupon;
        
	} // end inputChoice()

	// method name : couponJudge
	// return : boolean
	// arguments : String regex, String coupon
	// 기능 : 쿠폰의 조건이 유효한지 판정
	// 쿠폰의 조건에 적합하면 참, 적합하지 않으면 거짓값 리턴
	public static boolean couponJudge(String regex, String coupon) {
		boolean check = false;
		// Pattern 클래스의 pattern의 객체 생성
		// Regex(조건)을 coupon(입력 받은 문장)에서 컴파일(찾아서)하여 Pattern 객체로 생성
		Matcher matcher = Pattern.compile(regex).matcher(coupon);

		// find() : 패턴이 일치하면 true를 반환하고 그 위치로 이동
		// matches() : 패턴이 전체 문자열과 일치할 경우 true 반환
		if (matcher.matches()) {
			check = true;
		} else {
			check = false;
		}

		// 쿠폰 조건에 부합한지 판정한 결과를 메인에 넘겨줘야 함
		return check;
        
	} // end regExpTest()

} // end RegExp04Method

 


2. [과제] 대표적인 정규 표현식(구글링을 통해 풀기)

package com.lec.java.regexp05;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
/* 대표적인 정규 표현식 
 *  구글링 하면 대표적인 정규표현식들이 많이 구할수 있습니다.
 *  각 정규표현식들을 작성해보고
 *	매칭되는 문자열과 그렇지 않은 것들을 출력해봅시다.   
 */
public class RegExp05Main {

	public static void main(String[] args) {
		System.out.println("많이 쓰는 정규표현식");

		String regex, intput, title;
		String [] arrInput;
		
//		//─────────────────────────────────────────
//		title = "URL";
//		regex = "https?://(\\w*:\\w*@)?[-\\w.]+(:\\d+)?(/([\\w/_.]*(\\?\\S+)?)?)?"; 
//		arrInput = new String[] {
//				"http://www.forta.com/blog",
//				"https://www.forta.com:80/blog/index.html",
//				"http://www.forta.com",
//				"http://ben:password@www.forta.com/",
//				"www.naver.com",
//				"http:.naver.com",
//				"naver.com"
//		};
//		System.out.println(title);
//		regExpTest(regex, arrInput);

//		//─────────────────────────────────────────
//		title = "email";
//		regex = "(\\w+\\.)*\\w+@(\\w+\\.)+[A-Za-z]+"; // 이메일 주소를 검사할 수 있지만 호스트 이름에 IP 주소가 들어간 경우는 불가능
//		arrInput = new String[] {
//			"every5116@naver.com",
//			"s1122324254@melon.com",
//			"every5116",
//			"qlsskwhddls123@daum.net"
//		};
//		System.out.println(title);
//		regExpTest(regex, arrInput);

//		//─────────────────────────────────────────
//		title = "주민등록번호";
//		regex = "^(?:[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[1,2][0-9]|3[0,1]))-[1-4][0-9]{6}$";
//		arrInput = new String[] {
//				"810404-1234567",
//				"940505-2123456",
//				"000606-3123456",
//				"000707-4561234",
//				"710808-5123456",
//				"310808-1123456",
//				"311301-1123456",
//				"311139-1123456"
//		};
//		System.out.println(title);
//		regExpTest(regex, arrInput);
		
//		//─────────────────────────────────────────
//		title = "날짜 YYYY-MM-DD";
//		regex = "^(19|20)\\d{2}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[0-1])$"; 
//		arrInput = new String[] {
//			"2019-01-01",
//			"1994-04-04",
//			"1996-13-04",
//			"1998-05-63"
//		};
//		System.out.println(title);
//		regExpTest(regex, arrInput);
		
//		//─────────────────────────────────────────
//		title = "자연수";
//		regex = "^[1-9][0-9]*$"; 
//		arrInput = new String[] {
//			"9",
//			"09",
//			"-1",
//			"10"
//		};
//		System.out.println(title);
//		regExpTest(regex, arrInput);

//		//─────────────────────────────────────────
//		title = "정수";
//		regex = "^(0|-?[1-9][0-9]*)$"; // TODO
//		arrInput = new String[] {
//				"123",
//				"-123",
//				"01234"
//		};
//		System.out.println(title);
//		regExpTest(regex, arrInput);

//		//─────────────────────────────────────────
//		title = "소수";
//		regex = "[0-9]*\\.[0-9]*"; // TODO
//		arrInput = new String[] {
//				"0.01",
//				"1.1",
//				"1234"
//		};
//		System.out.println(title);
//		regExpTest(regex, arrInput);

//		//─────────────────────────────────────────
//		title = "소숫점 둘째자리까지";
//		regex = "^[0-9]+(.[0-9]{2})?$";
//		arrInput = new String[] {
//				"0.15",
//				"1.56",
//				"1.567"
//		};
//		System.out.println(title);
//		regExpTest(regex, arrInput);

		//─────────────────────────────────────────
		title = "통화표시 (₩)";
		regex = "^(₩[1-9])[0-9]*$"; // TODO
		arrInput = new String[] {
			"₩",
			"₩1",
			"₩01",
			"₩100"
		};
		System.out.println(title); 
		regExpTest(regex, arrInput);

		System.out.println("프로그램 종료");

	} // end main()

	// 도우미 함수
	public static void regExpTest(String regex, String[] arrInput) {
		for (String input : arrInput)
			regExpTest(regex, input);
	}

	public static void regExpTest(String regex, String input) {
		System.out.println("[정규표현식 매칭 테스트]-----------------");
		System.out.println("정규표현식: " + regex);
		System.out.println("입력문자열: " + input);

		if(Pattern.matches(regex, input)) {
			System.out.println("   ●매칭●");
		} else {
			System.out.println("   Ⅹ매칭 없슴Ⅹ");
		}
		
		System.out.println();
	} // end regExpTest()

} // end class

 

 

3. Lec14_Access
1) com.lec.java.access01 패키지, Access01Main, Test01 클래스 / com.lec.java.access02 패키지, Test02 클래스

** com.lec.java.access01 패키지, Access01Main 클래스

package com.lec.java.access01;

import com.lec.java.access02.Test02;
/*
 * 접근권한 수식어(Access Modifier)  접근제한자
 * 1) 종류: private, (default), protected, public
 *
 * 2) 기능
 * 	- 멤버 변수, 멤버메소드에 대한 접근 권한을 제한
 *
 * 3) private: '자기자신'이 선언된 클래스에서만 사용 가능
 *
 * 4) (default): '자기자신' + '같은 패키지'에 있는 클래스들에서는사용 가능
 *
 * 5) protected: '자기자신' + '같은 패키지' + '상속받은 클래스' 에서 사용 가능
 * 		다른 패키지의 클래스라도 '상속 받으면' 사용 가능하다
 *
 * 6) public: 어디서든 사용이 가능
 * 
 *
 * 사용범위: private < (default) < protected < public
 * 
 * ※ 클래스에 붙는 접근제한자는 딱 두가지 입니다
 * 	(default) , public
 */
public class Access01Main {

	public static void main(String[] args) {
		System.out.println("접근권한 수식어(Access Modifier)");
		
		Test01 t1 = new Test01();
		//t1.privatenum = 10;	// 오류 : not visible
		t1.defaultNum = 20;
		t1.protectedNum = 30;
		t1.publicNum = 40;
		
		//t1.privateMethod();	// 오류 : not visible
		t1.defaultMethod();
		t1.protectedMethod();
		t1.protectedMethod();
		
		// Ctrl + Shift + O : 자동으로 필요한 import와 불필요한 import는 없애거나 생성해준다
		Test02 t2 = new Test02(); 	// 다른 패키지에 있는 클래스는 반드시 import 필요
		
		//t2.privateNum = 10;	// 오류 
					// privateNum cannot be resolved or is not a field
		//t2.defaultNum = 20;	// 오류 : not visible 
		//t2.protectedNum = 40;	// 오류 : not visible
		t2.publicNum = 50;
		
		//t2.privateMethod();	// 오류 : not visible
		//t2.defaultMethod();	// 오류 : not visible 
		//t2.protectedMethod();	// 오류 : not visible 
		t2.publicMethod();
		
	} // end main()

} // end class Access01Main

 

** com.lec.java.access01 패키지 Test01 클래스 

package com.lec.java.access01;

public class Test01 {
	
	private int privatenum;
	int defaultNum;
	protected int protectedNum;
	public int publicNum;
	
	private void privateMethod() {}
	void defaultMethod() {}
	protected void protectedMethod() {}
	public void publicNum() {}

}

 

** com.lec.java.access02 패키지, Test02 클래스

package com.lec.java.access02;
// Alt + Shift + R : 이름 바꾸기
public class Test02 {
	
	private int privatenum;
	int defaultNum;
	protected int protectedNum;
	public int publicNum;
	
	private void privateMethod() {}
	void defaultMethod() {}
	protected void protectedMethod() {}
	public void publicMethod() {}

}

 

2) com.lec.java.access03 패키지, Access03Main, TestDefault, TestPublic 클래스 / 
    com.lec.java.access04 패키지, TestPublic, TestPublic2, TestDefault2 클래스

** com.lec.java.access03 패키지, Access03Main 클래스

package com.lec.java.access03;

import com.lec.java.access04.TestPublic2;

// 다른 패키지의 (default) 클래스는 import 불가
//import com.lec.java.access04.MyDefault2;

/*
 * 클래스의 접근 권한 수식어: public, (default)
 * 1. public class: 어디에서나 인스턴스 생성이 가능한 클래스
 * 		(주의) public 클래스의 이름은 .java 파일 이름과 반드시 같아야 함
 * 2. (default) class: 같은 패키지에 있는 클래스들에서만 인스턴스 생성이 가능
 */
public class Access03Main {

	public static void main(String[] args) {
		System.out.println("public, default 클래스");
		
		TestPublic t1 = new TestPublic();
		
		// 같은 패키지에 있는 클래스에서는 인스턴스 생성(사용) 가능
		MyDefault t2 = new MyDefault();
		
		// 다른 패키지에 있는 public 클래스
		// --> 인스턴스 생성 가능!!
		// 대신, import를 해줘야함!
		TestPublic2 t3 = new TestPublic2();
		
		// 다른 패키지에 있는 (default) 클래스
		// --> 인스턴스 생성 불가!!
		//MyDefault2 t4;
		
		// 다른 패키지의 클래스와 동일한 이름의 클래스가 충돌한다면?
		// 풀네임을 작성해야 함
		com.lec.java.access04.TestPublic t11 = 
				new com.lec.java.access04.TestPublic();
		
	} // end main()

} // end class Access03Main


** com.lec.java.access03 패키지, TestDefault 클래스

package com.lec.java.access03;

// 디폴트 클래스의 이름은 .java 파일의 이름과 같아야 할 필요는 없다.
class MyDefault {

}


** com.lec.java.access03 패키지, TestPublic 클래스

package com.lec.java.access03;

//public class는 클래스 안에 .java 파일 안에 1개밖에 존재 못함
public class TestPublic {

}

// (default) 클래스
class Test1{
	
}

class Test2{
	
}


** com.lec.java.access04 패키지, TestPublic 클래스

package com.lec.java.access04;

public class TestPublic {

}


** com.lec.java.access04 패키지, TestPublic2 클래스

package com.lec.java.access04;

public class TestPublic2 {

}


** com.lec.java.access04 패키지, TestDefault2 클래스

package com.lec.java.access04;

class MyDefault2 {
	
}

 

[추가] public class는 클래스 안에 1개 밖에 존재 못함

[추가] 다른 패키지에 있는 default 클래스 사용 불가

3) com.lec.java.final01 패키지, Final01Main 클래스

package com.lec.java.final01;

public class Final01Main {
	
	// final 멤버변수는
	// 반드시 선언과 동시에 초기화 해야 함.
	//final int NUM;	//오류
	
	// Ctrl + Shift + X : 대문자로 변경
	final int NUM = 1;
	
	public static void main(String[] args) {
		System.out.println("final: 변경할 수 없는 상수");
		
		int num1 = 1;
		num1 = 10;
		
		final int num2 = 1;
		//num2 = 10;	// 불가
				// The final local variable num2 cannot be assigned.
				// It must be blank and not using a compound assignment.
		
		final int num3;
		num3 = 1;		// final 지역변수는 선언 이후에 초기화 가능!

	} // end main()

} // end class Final01Main

 

[추가] 상수는 반드시 선언과 동시에 초기화 해야 한다!

[추가] 상수는 한 번 설정한 값 변경 불가!

4) com.lec.java.static01 패키지, Static01Main 클래스

package com.lec.java.static01;

import java.util.Scanner;
/* 
 * 클래스에 선언된 멤버 변수/멤버 메소드는
 * static 여부에 따라 아래와 같이 불려진다
 * 
 * 인스턴스 변수: 
 * 	static 이 안붙은 변수
 * 	인스턴스를 생성한 다음에(new 생성자(); 호출된 다음에)
 * 	사용할 수 있는 변수
 * 인스턴스 메소드:
 * 	static 이 안 붙은 메소드
 * 	인스턴스를 생성한 다음에(new 생성자(); 호출된 다음에)
 * 	사용할 수 있는 메소드
 * 
 * 클래스 변수(static 변수):
 * 	클래스의 멤버 변수들 중에서,
 * 	인스턴스를 생성하지 않아도 사용할 수 있는 변수
 * 클래스 메소드(static 메소드):
 * 	인스턴스를 생성하지 않아도 사용할 수 있는 메소드
 */
public class Static01Main {
	
	public static void test() {
		System.out.println("Hello static!");
	}
	
	public void test2() {
		System.out.println("Hello non-static!");
	}

	
	public static void main(String[] args) {
		System.out.println("인스턴스 변수/메소드 vs 클래스 변수/메소드");
		
		test();
		
		// static은 non-static 사용 불가
		//test2();	// 오류
				// Cannot make a static reference to the non-static method
		
		// 인스턴스 생성 이후에는 사용 가능
		Static01Main tc = new Static01Main();
		tc.test2();
		
	} // end main()

} // end class Static01Main


[추가] test2는 인스턴스 메소드, static은 non-static 사용 불가

5) com.lec.java.static02 패키지, Static02Main, Test 클래스
** Static02Main 클래스

package com.lec.java.static02;
/*
 * 클래스 변수 / 메소드 특징 (static)
 * 1. 메모리의 '메소드 영역'에 클래스가 로드 될때(프로그램 시작될때) '한번만' 생긴다 
 * 2. 인스턴스가 생성되지 않아도 사용할 수 있다.
 * 		- 클래스이름.static변수,  클래스이름.static메소드()  <-- 요렇게 사용한다
 * 3. 모든 인스턴스는 하나의 static 변수/메소드를 '공유'한다.
*/
public class Static02Main {

	public static void main(String[] args) {
		System.out.println("인스턴스 변수/메소드");
		
		// static 변수도 기본값으로 자동 초기화됨.
		System.out.println(Test.sNum);	// 출력값 : 0
		Test.show2();
		
		Test.sNum = 123;
		Test.show2();

		//Test.Num;			// 오류 
						// 왜? 인스턴스 변수는 인스턴스 후 사용 가능
		
		Test t = new Test();		// 인스턴스 생성
		t.num = 100;
		t.show();
		
		Test t2 = new Test();
		t2.num = 200;
		t2.show();
		
		Test.sNum = 999;
		t2.show();
		t2.sNum = 500;				// 사용 가능하나 권장하지 않는 방법
		t.show();
		
		Test.sNum = 100;
		t.sNum = 500;				// 사용 가능하나 권장하지 않는 방법
		t2.sNum = 700;				// 사용 가능하나 권장하지 않는 방법
		System.out.println(Test.sNum);
		System.out.println(t.sNum);		// 사용 가능하나 권장하지 않는 방법
		System.out.println(t2.sNum);		// 사용 가능하나 권장하지 않는 방법
		
	} // end main()

} // end class Static02Main

 

** Test 클래스

package com.lec.java.static02;

public class Test {
	int num;		// 인스턴스 변수
	static int sNum;	// 클래스 변수(static 변수)

	// 인스턴스 메소드
	public void show() {
		System.out.println("인스턴스 num = " + num);
		System.out.println("클래스(static) sNum = " + sNum);
	}
	
	// 클래스 (static) 메소드
	public static void show2() {
		//System.out.println("인스턴스 num = " + num); 	// 오류
								// Cannot make a static reference 
								// to the non-static field num
		System.out.println("클래스(static) sNum = " + sNum);
		
	}
}

 

[추가] static 메소드 안에 static 변수가 아닌 것은 사용 불가

6) com.lec.java.static03 패키지, Static03Main, Test 클래스
** Static03Main 클래스

package com.lec.java.static03;

import java.util.Calendar;
/*
 * Singleton 디자인 패턴
 * 생성되는 인스턴스가 최대 1개까지만 허용해야 하는 패턴 설계
 */
public class Static03Main {

	public static void main(String[] args) {
		System.out.println("Singleton 디자인 패턴");
		
//		Test t1 = new Test();
//		Test t2 = new Test(); 
		
		Test t1 = Test.getInstance();
		System.out.println("t1 : num = " + t1.getNum());
		t1.setNum(123);
		System.out.println("t1 : num = " + t1.getNum());
		
		Test t2 = Test.getInstance();
		System.out.println("t2 : num = " + t2.getNum());
		
		t2.setNum(500);
		System.out.println("t1 : num = " + t1.getNum());
		
		// Singleton 사용 예
		//Calendar c = new Calendar();
		Calendar c = Calendar.getInstance();
		
	} // end main()

} // end class Static03Main


** Test 클래스

package com.lec.java.static03;

public class Test {
	
	private int num;
	static int count = 0;
	
	
	// singleton 패턴
	// 기본생성자
	private Test() {
		count++;
		System.out.println(count + " 번째 인스턴스 생성");
	}
	
	private static Test instance = null;
	public static Test getInstance() {
		if(instance == null) {
			instance = new Test();	// 인스턴스 생성!
		
		} 
		return instance;
	}

	
	//getter, setter
	public int getNum() {return num;}
	public void setNum(int num) {this.num = num;}
	
	
}

 

 

4. Lec15_Inheritance
1) com.lec.java.inherit01 패키지, Inherit01Main, BasicTV, SmartTV 클래스

** Inherit01Main 클래스

package com.lec.java.inherit01;

public class Inherit01Main {

	public static void main(String[] args) {
		System.out.println("상속(Inheritance) 을 사용하지 않는 경우");

		BasicTV tv1 = new BasicTV();
		tv1.isPowerOn = true;
		tv1.volume = 10;
		tv1.channel = 5;
		tv1.displayInfo();
		
		// 시대가 지나고
		// 새로운 TV가 나왔다!!!
		// 그것은 바로......!!!!!!!!!
		// SmartTV라는 기능이 생기고
		// 새로운 기능이 생겼다!!!
		// 그럴때는 어떻게 해야할까???
		// 현재는 SmartTV라는 클래스를 만들어서 
		// 기존 기능과 새로 추가된 기능을 직접 타이핑을 했다..!!
		// 너무 힘들고 번거롭다 ㅜㅜ
		
		System.out.println("\n프로그램 종료");
	} // end main()
} // end class

 

** BasicTV 클래스

package com.lec.java.inherit01;

// 클래스: 멤버변수 (+ 생성자) + 메소드 => 데이터 타입
public class BasicTV {
	// 멤버 변수
	boolean isPowerOn;
	int channel;
	int volume;
	
	// 메소드
	public void displayInfo() {
		System.out.println("--- TV 현재 상태 ---");
		System.out.println("전원: " + isPowerOn);
		System.out.println("채널: " + channel);
		System.out.println("볼륨: " + volume);
	} // end displayInfo()
	
} // end class BasicTV

 

** SmartTV 클래스

package com.lec.java.inherit01;

public class SmartTV {
	// 멤버 변수
	boolean isPowerOn;
	int channel;
	int volume;
	String ip;	// SmartTV 에서 새롭게 추가된 필드
	
	// 메소드
	public void displayInfo() {
		System.out.println("--- TV 현재 상태 ---");
		System.out.println("전원: " + isPowerOn);
		System.out.println("채널: " + channel);
		System.out.println("볼륨: " + volume);
		System.out.println("IP주소: " + ip);	// SmartTV에서 추가된 코드
	} // end displayInfo()
	

}

 

2) com.lec.java.inherit02 패키지, Inherit02Main, BasicTV, SmartTV 클래스
** Inherit02Main 클래스

package com.lec.java.inherit02;
/* 상속 (Inheritance)
 * 	상위클래스를 상속받아서 하위클래스를 정의하는 방법
 *    class 하위클래스 extends 상위클래스
 *    
 *  자바 에선 오로지 '하나의 부모'로부터 상속받을수 있습니다 (단일 상속)  다중 상속 허용하지 않음
 *  
 *  (용어)
 *  Super Class(상위 클래스), Parent Class(부모/조상 클래스), Basic Class(기본 클래스)
 *  Sub Class(하위 클래스), Child Class(자식 클래스), Derived Class(유도 클래스)
 *  	※ 상속받는다..(동사) inherit , subclass
 *  
 *  sub class에서는 super class가 가지고 있는 멤버 변수들은  선언하지 않아도 사용할 수 있다.
 *  super class에 없는 멤버 변수만 선언해 주면 됨
 *  
 *  상속의 이점 :
 *  상속을 통하여 기존의 객체를 그대로 활용하면서, 새로운 객체에서
 *  추가, 변경되는 부분만 작성함으로 소프트웨어 개발 효율을 높일수 있다.
*/
public class Inherit02Main {

	public static void main(String[] args) {
		System.out.println("상속 (Inheritance)");
        
		// 아까의 번거로움을 상속을 통해 극복...!!
		// 기존 코드는 상속을 통해 물려 받고
		// 새롭게 추가해야하는 코드만 작성해주면 됨!!

		// BasicTV 클래스의 인스턴스 생성
		BasicTV tv1 = new BasicTV();
		tv1.displayInfo();
		
		System.out.println();

		// SmartTV 클래스의 인스턴스 생성
		SmartTV tv2 = new SmartTV();
		tv2.isPowerOn = true;
		tv2.channel = 100;
		tv2.volume = 10;
		tv2.ip = "192.168.0.110";
		tv2.displayInfo();
		
		System.out.println("\n프로그램 종료");
	} // end main()
    
} // end class


** BasicTV 클래스

package com.lec.java.inherit02;

public class BasicTV {
	// 멤버 변수
	boolean isPowerOn;
	int channel;
	int volume;
	
	// 메소드
	public void displayInfo() {
		System.out.println("--- TV 현재 상태 ---");
		System.out.println("전원: " + isPowerOn);
		System.out.println("채널: " + channel);
		System.out.println("볼륨: " + volume);
	} // end displayInfo()
	
} // class BasicTV


** SmartTV 클래스

package com.lec.java.inherit02;

// BasicTV
//   └SmartTV
public class SmartTV extends BasicTV {
	String ip;
	
	@Override
	public void displayInfo() {
		super.displayInfo();
		System.out.println("IP주소: " + ip);
	}
	
}

 

3) com.lec.java.inherit03 패키지, Inherit03Main, Person, BusinessPerson 클래스
** Inherit03Main 클래스

package com.lec.java.inherit03;
/* java.lang.Object
 * 	자바의 모든 클래스는 java.lang.Object로부터 상속 받는다.
 *  java.lang.Object 클래스는 모든 클래스의 부모클래스이다.
 *  Object 클래스에 있는 메소드를 다른 클래스에서도 사용 가능
 */
public class Inherit03Main {

	public static void main(String[] args) {
		System.out.println("상속 연습");
		System.out.println("java.lang.Object");
		
		System.out.println();
		Person p1 = new Person();
		p1.name = "홍길동";
		p1.whoAmI();

		System.out.println();
		BusinessPerson p2 = new BusinessPerson();
		p2.name = "허균";
		p2.whoAmI();
		p2.company = "(주)조선";
		p2.showInfo();
		
		System.out.println();
		System.out.println(p2);	// 내부적으로는 p2.toString() 의 결과값이 출력
					// 출력값: com.lec.java.inherit03.BusinessPerson@15db9742
		System.out.println(p2.toString());	// toString()은 Object 소속 메소드 
					// 출력값 : com.lec.java.inherit03.BusinessPerson@15db9742
		
		System.out.println("\n프로그램 종료");
	} // end main()
    
} // end class


** Person 클래스

package com.lec.java.inherit03;
public class Person {
	String name;
	public void whoAmI() {
		System.out.println("제 이름은 " + name + " 입니다.");
	}
}

 

** BusinessPerson 클래스

package com.lec.java.inherit03;
public class BusinessPerson extends Person {
	String company;
	public void showInfo() {
		whoAmI();
		System.out.println("회사는 " + company + " 다닙니다.");
	}
}

 

[추가] 자바의 모든 클래스는 java.lang.Object 상속 받는다

4) com.lec.java.inherit04 패키지, Inherit04Main, Vehicle, Car, HybridCar 클래스

** Inherit04Main 클래스

package com.lec.java.inherit04;
// 생성자의 목적: 인스턴스 생성시 멤버변수들의 초기화
/* 상속에서 생성자 호출순서
 *   1. 자식 클래스의 생성자에서 명시적으로 부모 클래스의 생성자가
 *      호출되지 않으면, 자동으로 부모 클래스의 "디폴트 생성자"가 호출됨.
 *   
 *   2. 자식 클래스의 생성자에서 명시적으로 부모 클래스의 생성자를 호출하기도 함
 *   	1) super(...) 키워드 사용 -> 부모 클래스의 생성자를 호출
 *   	2) (주의) super는 항상 제일 처음에 호출되어야 함
 *   	3) 부모 클래스에 디폴트 생성자가 없는 경우도 있을 수 있다.
 *   그런 경우에는 다른 생성자를 "반드시 명시적으로 호출"해 줘야만 함.
*/
public class Inherit04Main {

	public static void main(String[] args) {
		System.out.println("상속과 생성자");
		
		System.out.println();
		// Vehicle 클래스의 인스턴스 생성
		Vehicle v1 = new Vehicle();
		Vehicle v2 = new Vehicle(100);
		
		System.out.println();
		// Car 클래스의 인스턴스 생성
		Car car1 = new Car();
		Car car2 = new Car(2000);
		System.out.println(car2.speed);
		System.out.println(car2.oil);
		Car car3 = new Car(80, 3000);
		
		System.out.println();
		// HybridCar 클래스의 인스턴스 생성
		HybridCar h1 = new HybridCar();
		System.out.println(h1.electricity);
		System.out.println(h1.oil);
		System.out.println(h1.speed);
		
		System.out.println();
		Car car4 = new Car(3.14);

		System.out.println("\n프로그램 종료");
	} // end main()
    
} // end class


** Vehicle 클래스

// 생성자의 목적: 인스턴스 생성시 멤버변수들의 초기화
package com.lec.java.inherit04;

public class Vehicle {
	
	int speed;
	
	// 1
	public Vehicle() {
		System.out.println("Vehicle() 생성");
	}
	
	// 2
	public Vehicle(int speed) {
		this.speed = speed;
		System.out.println("Vehicle(int) 생성 : speed = " + speed);
	}
    
}

 

** Car 클래스

// 생성자의 목적: 인스턴스 생성시 멤버변수들의 초기화
package com.lec.java.inherit04;

public class Car extends Vehicle {
	
	int oil;
	
	// 1
	public Car() {
		// 부모클래스의 기본 생성자 호출 --> Vehicle()
		// 명시적으로 super 생성자가 없으면 부모의 기본 생성자를 호출하게 됨.
		System.out.println("Car() 생성");
	}
	
	// 2
	public Car(int oil) {
		super();	// super : 부모를 의미, super() <-- 부모의 기본생성자 호출
				// super();는 반드시 생성자 코드의 '첫번째 문장'이어야 함!!!!
		this.oil = oil;
		System.out.println("Car(int) 생성 : oil = " + oil);
	}
	
	// 3
	public Car(int speed, int oil) {
		super(speed);	// super(int) <-- 부모생성자 호출
		this.oil = oil;
		System.out.println("Car(int, int) 생성 : speed = " + speed
				+ ", oil = " + oil);
	}
	
	public Car(double value) {
		this(555, (int)value);	// 생성자 위임(delegation)
		//super(100);		// 오류 : this와 super는 양립할 수 없음
					// Constructor call must be the first statement in a consructor
		System.out.println("Car(double) 생성 : value = " + value);
	}
	
}

 

** HybridCar 클래스

package com.lec.java.inherit04;

public class HybridCar extends Car {
	
	int electricity;
	
	public HybridCar() {
		System.out.println("HybridCar() 생성");
	}

}

 

[추가] this와 super는 양립할 수 없음

5) com.lec.java.inherit07 패키지 Inherit07Main, Person, BusinessPerson 클래스
** Inherit07Main 클래스

package com.lec.java.inherit07;
/* 메소드 재정의(Overriding)
 * '상속'관계에서 '부모 클래스에 있던 메소드'를 '재정의'하는 것.
 *  부모 클래스에 있는 메소드와 매개변수 리스트가 동일해야 함
 *  부모 클래스에 있는 메소드와 접근권한 수식어가 동일할 필요는 없지만,
 *  접근권한의 범위가 축소될 수는 없다.
 *  즉, 접근권한은 같거나 더 넓은 수식어를 사용해야 함.
 *  
 *    ! 메소드 오버로딩(Overloading)과 혼돈하지 말자!
 *     
 * final 메소드 : 더이상 오버라이딩 불가
 * final 클래스 : 더이상 상속 불가 
 * final 변수 : 한 번 초기 값이 설정되면 변경 불가
 */
public class Inherit07Main {

	public static void main(String[] args) {
		System.out.println("상속: Method Overriding(재정의)");
		
		System.out.println();
		// Person 클래스의 인스턴스 생성
		Person p1 = new Person();
		p1.setName("abc");
		p1.showInfo();		// Person의 showInfo()
		
		
		System.out.println();
		// BusinessPerson 클래스의 인스턴스를 생성
		BusinessPerson p2 = new BusinessPerson();
		p2.setName("아이언맨");
		p2.setCompany("스타크인더스트리");
		p2.showInfo();		// BusinessPerson에서 Overriding한 showInfo()
		
		System.out.println();
		p2.whoAreYou();
		
		System.out.println();
		System.out.println(p2);	// p2.toString()
		
		
		System.out.println("\n프로그램 종료");
	} // end main()
	
} // end class


** Person 클래스

package com.lec.java.inherit07;

//final 클래스는 더이상 상속 불가 
//public final class Person {
public class Person {
	
	private String name;
	
	public Person() {}

	public String getName() {return name;}
	public void setName(String name) {this.name = name;}
	
	public void showInfo() {
		System.out.println("이름 : "+ name);
	}

	// final 메소드 : 더이상 오버라이딩 불가
	final public void whoAreYou() {
		System.out.println("이름 : " + name);
	}

}

 

** BusinessPerson 클래스

package com.lec.java.inherit07;

public class BusinessPerson extends Person {
	
	private String company;

	// getter & setter : Alt + Shift + S + R 
	public String getCompany() {return company;}
	public void setCompany(String company) {this.company = company;}
	
	// 메소드 재정의(Overriding)
	@Override			// annotation : 애노테이션.
	public void showInfo() {
		super.showInfo();	// 부모의 기능을 그대로 받아서 쓸게요!!!
		System.out.println("회사 : " + company);
	}
	
	// 메소드 오버로딩(Overloading) 
	// 메소드 중복 정의 : 같은 이름으로 메소드를 매개변수 리스트를 달리하여 중복 정의
	// 즉, 이름이 같아도 메소드 signature 가 다르면 중복정의 가능.
	public void showInfo(int id) {
		System.out.println("id : " + id);
		showInfo();
	}
	
	// Person 클래스에 있는 whoAreYou()메소드는 final 메소드이기 때문에
	// 오버라이딩 불가..!!
//	@Override
//	public void whoAreYou() {
//		super.whoAreYou();
//		
//	}
	
	@Override
	public String toString() {
		return "BusinessPerson: " + getName() + " " + company;
	}

}

 

[추가] final 클래스는 더이상 상속 불가

6) com.lec.java.inherit10 패키지, Inherit10Main 클래스

package com.lec.java.inherit10;
/*
	final 메소드 
		더이상 오버라이딩 될수 없는 메소드
 */
/*
	메소드 오버라이딩(Overriding), 재정의
	부모 클래스에 있는 메소드를
	자식 클래스에서 리턴 타입, 매개변수 모두 동일하게 유지하면서
	메소드의 본체를 다시 정의하는 것
	접근권한(private, (default), protected, public)도 동일하게 유지하는 것이
	일반적이지만,
	접근 범위를 더 넓게 변경하는 것은 가능. 하지만 좁히는 것은 허용 안됨.
*/
public class Inherit10Main {

	public static void main(String[] args) {
		System.out.println("final 메소드");

		System.out.println("\n프로그램 종료");
	} // end main()
} // end class

class TestSuper{
	
	private void test1() {
		System.out.println("부모 private 메소드");
	}
	void test2() {
		System.out.println("부모 default 메소드");
	}
	protected void test3() {
		System.out.println("부모 protected 메소드");
	}
	public void test4() {
		System.out.println("부모 public 메소드");
	}

}

// private < (default) < protected < public
// 접근 범위를 더 넓게 변경하는 것은 가능. 하지만 좁히는 것은 허용 안됨.
// 리턴 타입, 매개변수 모두 동일하게 설정해야 한다.
class TestSub extends TestSuper {

	// private void test1()는 오버라이딩 아예 불가!!

	@Override
	//private void test2() {		// 불가
	void test2() {
		// TODO Auto-generated method stub
		super.test2();
	}

	@Override
	// private void test3() {		// 불가
	// default void test3() {		// 불가
	// public private void test3() {	// 가능
	protected void test3() {
		super.test3();
	}

	@Override
	// 좁히는 것이 안되기 때문에 public 이외에 사용 불가
	public void test4() {
		// TODO Auto-generated method stub
		super.test4();
	}
		
}

 

 

5. Lec16_OOP
1) com.lec.java.oop01 패키지, Polymorphism01Main, Vehicle, Car, HybridCar 클래스 

** Polymorphism01Main 클래스

package com.lec.java.oop01;
/*
 	다형성  ( Polymorphism )
 		하나의 이름의 클래스나 메소드가 '여러 가지 형태의 동작을 하는 능력'
 	
 	클래스의 다형성:
	 	한 타입의 참조변수로 여러타입의 객체를 참조 가능.
	 	조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조가능한것
 	
 	메소드의 다형성:
 		메소드 오버로딩, 메소드 오버라이딩
 	
*/
public class Polymorphism01Main {

	public static void main(String[] args) {
		System.out.println("다형성(Polymorphism)");
		
		Vehicle v1 = new Vehicle();
		Car c1 = new Car();
		HybridCar h1 = new HybridCar();
		
		v1.displayInfo();
		c1.displayInfo();
		h1.displayInfo();
		
		System.out.println();
		
		// 자손 타입은 조상 타입으로 자동형변환 가능하다
		Vehicle car1 = new Vehicle();	
		Vehicle car2 = new Car();	// Car IS-A Vehicle
		Vehicle car3 = new HybridCar();	// Car IS-A HybridCar
		
		// 인스턴스 타입의 메소드가 실행된다.
		car1.displayInfo();
		car2.displayInfo();
		car3.displayInfo();
		
		Car car4 = new HybridCar();
		
		//HybridCar car5 = new Car();	// 오류 : 불가능 자손 <-- 조상 (X)
						// Type mismathch : cannot convert from Car to HybridCar
		
        
		System.out.println("\n 프로그램 종료");
	} // end main()

} // end class

 

** Vehicle 클래스 

package com.lec.java.oop01;

public class Vehicle {

	private int speed;
	
	public int getSpeed() {return this.speed;}
	public void setSpeed(int speed) {this.speed = speed;}
	
	public void displayInfo() {
		System.out.println("--- Vehicle 정보 ---");
		System.out.println("speed: " + speed);
	}
}

 

** Car 클래스 

package com.lec.java.oop01;

public class Car extends Vehicle {
	
	private int oil;

	public int getOil() {return oil;}
	public void setOil(int oil) {this.oil = oil;}
	
	@Override
	public void displayInfo() {
		System.out.println("--- Car 정보 ---");
		System.out.println("speed: " + getSpeed());
		System.out.println("oil: " + oil);
	}
	
}

 

** HybridCar 클래스

package com.lec.java.oop01;

public class HybridCar extends Car {
	
	private int electricity;

	public int getElectricity() {return electricity;}
	public void setElectricity(int electricity) {this.electricity = electricity;}
	
	@Override
	public void displayInfo() {
		System.out.println("--- HybridCar 정보 ---");
		System.out.println("speed: " + getSpeed());
		System.out.println("oil: " + getOil());
		System.out.println("electricity: " + electricity);
	}

}

 

 

2) com.lec.java.oop02 패키지, Polymorphism02Main, Vehicle, Car, HybridCar 클래스 

** Polymorphism02Main 클래스

package com.lec.java.oop02;
/* 다형성의 유용성
	다형성에 의해서, 자식타입 객체가 부모타입으로 자동 형변환 가능!
	부모타입 만으로도 상속된 모~든 자손 타입들을 담을수 있다.
*/
public class Polymorphism02Main {

	public static void main(String[] args) {
		System.out.println("다형성의 사용 (유용성)");

		// 다형성에 의해서, 자손타입 객체가 조상타입으로 자동 형번환 가능
		Vehicle car1 = new Vehicle();
		Vehicle car2 = new Car();
		Vehicle car3 = new HybridCar();
		
		// 다형성의 유용함1
		// 조상타입으로 모~~든 자손 타입들을 담을 수 있다.
		Vehicle[] car = new Vehicle[3];
		car[0] = new Vehicle();
		car[1] = new Car();
		car[2] = new HybridCar();
		
		// car 라는 하나의 이름의 변수로 여러가지 타입의
		// 오버라이딩 된 메소드가 각각 동작시킬 수 있다.
		for (int i = 0; i < car.length; i++) {
			car[i].displayInfo();
		}
		
		// 다형성이 없었다면?  
		// 각 타입별로 변수들을 만들고 따로따로 사용해야 하는 왕불편.
		//Vehicle car1 = new Vehicle();
		//Car car2 = new Car();
		//HybridCar car3 = new HybridCar();
		//car1.displayInfo();		
		//car2.displayInfo();
		//car3.displayInfo();

		// 다형성의 유용함2
		// 다형성의 유용함은 매개변수, 혹은 리턴 타입에도 적용된다.
		// println의 매개변수로 Object의 참조변수가 넘겨지면,
		// 내부적으로 해당 클래스의 toString() 메소드가 불리게 됨
		System.out.println(car1);
		System.out.println(car2);
		System.out.println(car3);
		
		System.out.println();
		for (int i = 0; i < car.length; i++) {
			System.out.println(car[i]);
		}

		driveCar(new Vehicle(), 100);
		driveCar(new Car(), 200);
		driveCar(new HybridCar(), 300);
		
		// instanceof 연산자
		// 용법 : 변수/값 instanceof 클래스
		// 결과 : true / false
		System.out.println(car1 instanceof Vehicle);
		System.out.println(car1 instanceof Car);
		System.out.println(car2 instanceof Vehicle);
		System.out.println(car2 instanceof HybridCar);
		
		
		System.out.println("\n 프로그램 종료");
	} // end main()
	
	public static void driveCar(Vehicle v, int speed) {
		v.setSpeed(speed);
		v.displayInfo();
	}
	
} // end class

 

** Vehicle 클래스

package com.lec.java.oop02;

public class Vehicle {

	private int speed;
	
	public int getSpeed() {return this.speed;}
	public void setSpeed(int speed) {this.speed = speed;}
	
	public void displayInfo() {
		System.out.println("--- Vehicle 정보 ---");
		System.out.println("speed: " + speed);
	}
}

 
** Car 클래스 

package com.lec.java.oop02;

public class Car extends Vehicle {
	
	private int oil;

	public int getOil() {return oil;}
	public void setOil(int oil) {this.oil = oil;}
	
	@Override
	public void displayInfo() {
		System.out.println("--- Car 정보 ---");
		System.out.println("speed: " + getSpeed());
		System.out.println("oil: " + oil);
	}
	
	
}


** HybridCar 클래스

package com.lec.java.oop02;

public class HybridCar extends Car {
	
	private int electricity;

	public int getElectricity() {return electricity;}
	public void setElectricity(int electricity) {this.electricity = electricity;}
	
	@Override
	public void displayInfo() {
		System.out.println("--- HybridCar 정보 ---");
		System.out.println("speed: " + getSpeed());
		System.out.println("oil: " + getOil());
		System.out.println("electricity: " + electricity);
	}
	
}

 

3) com.lec.java.oop03 패키지, Polymorphism03Main, Vehicle, Car, HybridCar 클래스

** Polymorphism03Main 클래스

package com.lec.java.oop03;

public class Polymorphism03Main {

	public static void main(String[] args) {
		System.out.println("다형성의 어려움");

		Vehicle car1 = new Vehicle();
		Vehicle car2 = new Car();
		Vehicle car3 = new HybridCar();
		
		car2.setSpeed(10);
		//car2.setOil(100);	// 오류, car2는 Vehicle 타입이기 때문에! 
					// The method setOil(int) is undefined for the type Vehicle
					// car2는 Vehicle 타입으로 선언되어 있으므로,
					// Vehicle이 아닌 다른 클래스(심지어 자식 클래스이더라도)에 정의된
					// 메소드는 사용할 수 없다.
					// 따라서, 실제로는 Car 타입 인스턴스로 생성되긴 했지만,
					// Vehicle 타입 참조변수로는 Car 클래스에 있는 메소드를 사용할 수 없다
		
		((Car)car2).setOil(100);
		// 실제로 Car 클래스의 인스턴스로 생성된 car2 변수는
		// 형변환(casting)을 통해서 Car 타입으로 변환할 수 있고,
		// Car 클래스에 정의된 메소드를 사용할 수 있다.
		
		//((Car)car1).setOil(10); // 오류 : java.lang.ClassCastException
					// ClassCastException 발생:
					// 실제로 Vehicle 클래스의 인스턴스로 생성된 car1을 
					// 자식 클래스인 Car로 강제 형변환을 하게 되면 문제가 발생할 수 있다.
					// 예외는 setOil()을 호출하는 과정이 아니라, 형변환하는 과정에서 발생된다
		
		System.out.println("\n 프로그램 종료");
	} // end main()

} // end class

** Vehicle 클래스

package com.lec.java.oop03;

public class Vehicle {

	private int speed;
	
	public int getSpeed() {return this.speed;}
	public void setSpeed(int speed) {this.speed = speed;}
	
	public void displayInfo() {
		System.out.println("--- Vehicle 정보 ---");
		System.out.println("speed: " + speed);
	}
}


** Car 클래스

package com.lec.java.oop03;

public class Car extends Vehicle {
	
	private int oil;

	public int getOil() {return oil;}
	public void setOil(int oil) {this.oil = oil;}
	
	@Override
	public void displayInfo() {
		System.out.println("--- Car 정보 ---");
		System.out.println("speed: " + getSpeed());
		System.out.println("oil: " + oil);
	}
		
}

 

** HybridCar 클래스

package com.lec.java.oop03;

public class HybridCar extends Car {
	
	private int electricity;

	public int getElectricity() {return electricity;}
	public void setElectricity(int electricity) {this.electricity = electricity;}
	
	@Override
	public void displayInfo() {
		System.out.println("--- HybridCar 정보 ---");
		System.out.println("speed: " + getSpeed());
		System.out.println("oil: " + getOil());
		System.out.println("electricity: " + electricity);
	}
	
}

 

4) com.lec.java.oop04 패키지, Abstract01Main 클래스

package com.lec.java.oop04;
/*
 클래스: 멤버 변수 (+ 생성자) + 메소드 => 데이터 타입
 추상 클래스(abstract class): 
    추상 메소드를 가지고 있는 클래스
    클래스 선언할 때 abstract 키워드를 반드시 써 줘야 함
    추상 클래스는 인스턴스를 생성할 수 없다. (new 불가능)
 
 추상 메소드(abstract method):
   원형(prototype)만 선언돼 있고, 메소드 본체가 정의되지 않은 메소드
   메소드 본체가 없기 때문에 {}부분이 없다.
   메소드 원형 끝에 ;으로 끝냄.
   메소드 이름 앞에 abstract 키워드를 반드시 써 줘야 함

 추상 클래스를 사용하는 목적은
   추상 클래스를 상속 받는 자식 클래스에 반드시 구현(implement)해야 할 메소드가 있을 경우,
   그 메소드를 추상메소드로 만들어서 반드시 override하도록 하는데 목적이 있다.
*/
public class Abstract01Main {

	public static void main(String[] args) {
		System.out.println("추상 클래스(abstract class)");
		
		// 추상클래스는 인스턴스 생성 불가능!
		//TestAbstract test1 = new TestAbstract();	// 오류
								// Cannot instantiate the type TestAbstract
		
		TestClass test2 = new TestClass();
		test2.test = 100;
		test2.testMethod();
		
		// 다형성
		TestAbstract test3 = new TestClass();
		test3.testMethod();
		
		System.out.println("\n 프로그램 종료");
	} // end main()

} // end class

abstract class TestAbstract {
	int test;
	
	public int getTest() {return this.test;}
	
	// 추상메소드 : 바디가 없는 메소드
	public abstract int testMethod();
}

// 추상클래스를 상속받는 클래스는 반드시 추상메소드를 반드시 구현(implement) 해야 함.
// 추상 메소드 본체 ({ ... }) 를 만들어 주어야 함.
class TestClass extends TestAbstract {

	@Override
	public int testMethod() {
		// TODO Auto-generated method stub
		return 0;
	}
	
}

abstract class TestClass2 extends TestAbstract {
	int number;
}

 

5) com.lec.java.oop05 패키지, Interface01Main 클래스

package com.lec.java.oop05;
/*
 인터페이스(interface):
 1. 모든 메소드가 public abstract으로 선언되고,
 2. 모든 멤버 변수가 public static final로 선언된
 특별한 종류의 추상 클래스

 인터페이스는 interface라고 선언
 인터페이스를 구현(상속)하는 클래스에서는 implements 키워드를 사용
 인터페이스를 구현(상속)할 때는 개수 제한이 없다. (다중상속!)
 메소드 선언에서 public abstract는 생략 가능
 멤버 변수 선언에서 public static final은 생략 가능
*/
public class Interface01Main {

	public static void main(String[] args) {
		System.out.println("인터페이스(interface)");
		
		//TestInterface t1 = new TestInterface();	// 오류: 추상메소드를 가지고 있는 존재는 new 불가
								// Cannot instantiate the type TestInterface
		
		TestImpl test1 = new TestImpl();
		test1.testAAA();
		test1.testBBB();
		
		TestImpl2 test2 = new TestImpl2();
        
		System.out.println(test1.MIN);
		//System.out.println(test2.MIN);	// 모호성 오류 : The field test2.MIN is ambiguous
		System.out.println(TestInterface.MIN);	// static은 static 방법으로 사용하자!
		System.out.println(TestInterface2.MIN);
		
		System.out.println("\n 프로그램 종료");
	} // end main()

} // end class

interface TestInterface {
		
	// 모든 멤버변수가 public static final
	public static final int MIN = 0;
	int MAX = 100;	// public static final 생략 가능
	public static String JAVA_STRING = "Java";
	String KOTLIN_STRING = "Kotlin";
	
	
	// 모든 메소드는 public abstract
	public abstract void testAAA();
	void testBBB();	// public abstract 생략 가능
	
}

interface TestInterface2 {
	public static final int MIN = 1;
	public abstract void testAAA();
	public abstract void testCCC();
}


// 인터페이스는 인스턴스를 생성할 수 없고
// 다른 클래스에서 구현(implement) 해야 함
class TestImpl implements TestInterface {

	@Override
	public void testAAA() {
		System.out.println("AAA");
	}

	@Override
	public void testBBB() {
		System.out.println("BBB");
	}
	
}

// 인터페이스는 다중 상속이 가능하다
class TestImpl2 implements TestInterface, TestInterface2 {

	@Override
	public void testCCC() {
		System.out.println("CCC");
	}

	@Override
	public void testAAA() {
		System.out.println("AAA");
	}

	@Override
	public void testBBB() {
		System.out.println("BBB");
	}
	
}


6) com.lec.java.oop06 패키지 Interface02Main 클래스, Menu 인터페이스

** Interface02Main 클래스

package com.lec.java.oop06;

import java.util.Scanner;

public class Interface02Main {

	public static void main(String[] args) {
		System.out.println("인터페이스");

		 Scanner sc = new Scanner(System.in);
		 System.out.println("메뉴선택: ");
		 int menu = sc.nextInt();
		 sc.close();
         
		switch(menu) {
		case 0:
			System.out.println("프로그램 종료");
			return;
		case 1:
			System.out.println("입력메뉴");
			break;
		case 2:
			System.out.println("검색메뉴");
			break;
		default:
			System.out.println("잘못 입력했습니다");
		}

		 switch(menu) {
		 case Menu.MENU_QUIT:
			 System.out.println(Menu.STR_QUIT);
			 return;
		 case Menu.MENU_INSERT:
			 System.out.println(Menu.STR_INSERT);
			 break;
		 case Menu.MENU_SERCH: 
			 System.out.println(Menu.STR_SEARCH);
			 break;
		 default:
			 System.out.println(Menu.STR_ERROR);
		 }
		
		System.out.println("\n 프로그램 종료");
	} // end main()

} // end class

 

** Menu 인터페이스

package com.lec.java.oop06;

public interface Menu {
	public static final int MENU_QUIT = 0;
	public static final int MENU_INSERT = 1;
	public static final int MENU_SEARCH = 2;
	
	public static final String STR_QUIT = "프로그램을 종료합니다.";
	public static final String STR_INSERT = "입력 메뉴";
	public static final String STR_SEARCH = "검색 메뉴";
	public static final String STR_ERROR = "잘못 입력했습니다.";
}

 

 

6. 전화번호부 v1.0
** PhonebookMain

package phonebook01.class01;

import java.util.Scanner;

public class PhonebookMain {

	Scanner sc;
	PhonebookModel [] bookData = new PhonebookModel[5]; 
	
	public static void main(String[] args) {
		PhonebookMain app = new PhonebookMain();
		app.init();   // 초기화
		app.run();   // 실행
		app.exit();   // 종료
	} // end main()
	
	// 응용프로그램을 초기화 
	public void init() {
		sc = new Scanner(System.in);
	}
	
	// 응용프로그램 구동
	public void run() {
		System.out.println("전화번호부 v1.0");
		
		while(true) {
			showMenu();  // 메뉴 표시
			
			int menu = sc.nextInt(); // 메뉴 입력
			sc.nextLine();
			
			switch(menu) {
			case 1:
				System.out.println("전화번호부를 입력합니다");
				insertPhoneBook();
				break;
			case 2:
				System.out.println("전화번호부 출력(열람)");
				showPhoneBook();
				break;
			case 3:
				System.out.println("프로그램을 종료합니다");
				return;
			default:
				System.out.println("잘못 입력하셨습니다");
			}
			
		} // end while	
	} // end run()
	
	// 응용프로그램 종료
	public void exit() {
		sc.close();
	}	
	
	// 전화번호부 입력
	public void insertPhoneBook() {
		
		// 전화번호부가 다 찼는지 체크
		int i;
		for(i = 0; i < bookData.length; i++) {
			if(bookData[i] == null) {break;}
		}
		// 다 찼으면 입력불가 처리
		if(i == bookData.length) {
			System.out.println("전화번호부가 다 찼습니다");
			return;
		}
		
		// 이름, 전화번호, 이메일 입력
		System.out.print("이름 입력:");
		String name = sc.nextLine();

		System.out.print("전화번호 입력:");
		String phoneNum = sc.nextLine();
		
		System.out.print("이메일 입력:");
		String email = sc.nextLine();
		
		// --> PhonebookModel 인스턴스 생성
		PhonebookModel pb = new PhonebookModel(name, phoneNum, email);
		
		// 배열에 추가
		bookData[i] = pb;
		System.out.println((i + 1) + "번째 전화번호부 추가 성공");
	}
	
	// 전화번호부 출력
	public void showPhoneBook() {
		// 배열안에 저장된 전화번호부들 출력.
		int i;
		for(i = 0; i < bookData.length; i++) {
			PhonebookModel pb = bookData[i];
			if(pb == null) {break;}
			
			System.out.println(pb);
		}
		System.out.println(i + " 개의 전화번호부 출력");
	}
	
	
	
	public void showMenu() {
		System.out.println();
		System.out.println("전화번호부 프로그램");
		System.out.println("------------------");
		System.out.println("[1] 입력");
		System.out.println("[2] 열람");
		System.out.println("[3] 종료");
		System.out.println("------------------");
		System.out.print("선택: ");
	}

} // end class


** PhonebookModel

package phonebook01.class01;

public class PhonebookModel {
	// 멤버 변수
	private String name;	// 이름
	private String phoneNum;	// 전화번호
	private String email;	// 이메일
	
	// 기본 생성자
	public PhonebookModel() {
		this.name = "";
		this.phoneNum = "";
		this.email = "";
	}

	//매개변수 생성자
	public PhonebookModel(String name, String phoneNum, String email) {
		super();
		this.name = name;
		this.phoneNum = phoneNum;
		this.email = email;
	}

	// getter & setter
	public String getName() {return name;}
	public void setName(String name) {this.name = name;}

	public String getPhoneNum() {return phoneNum;}
	public void setPhoneNum(String phoneNum) {this.phoneNum = phoneNum;}

	public String getEmail() {return email;}
	public void setEmail(String email) {this.email = email;}
	
    
	@Override
	public String toString() {
		String str = String.format("이름: %s, 전화번호: %s, 이메일: %s", name, phoneNum, email);
		return str;
	}

}

'웹_프론트_백엔드 > JAVA프레임윅기반_풀스택' 카테고리의 다른 글

2020.03.26  (0) 2020.03.26
2020.03.25  (0) 2020.03.25
2020.03.23  (0) 2020.03.23
2020.03.20  (0) 2020.03.20
2020.03.19  (0) 2020.03.19