부모형태에서 자식형태로 형변환 - 다운캐스팅

자식형태에서 부모형태로 형변환 - 업캐스팅

 

업캐스팅 ( upcasting )

package upcasting;

class A01{
	public void test() {
		System.out.println("aaaa");
	}
}
class B01 extends A01{
	public void test() {
		System.out.println("bbbb");
	}
}
class C01 extends A01{	
	public void test() {
		System.out.println("cccc");
	}
}

public class Ex01 {
	public static void main(String[] args) {
		A01 a;
		// 자식 클래스를 부모 클래스 자료형 형태로 저장 = 업캐스팅
		a = new B01(); a.test(); // bbbb
		a = new C01(); a.test(); // cccc
		
		
		/*
		B01 b;
		C01 c;
		b = new B01(); // b 객체화
		c = new C01(); // c 객체화
		b.test(); // bbbb 출력
		c.test(); // cccc 출력
		*/
	}
}

업캐스팅 예시 ( 위와 같이 업캐스팅한 경우 부모 자료형 변수 a 에 자식 클래스를 객체화 시키면 메소드가 오버라이딩되기 때문에 자식 클래스의 메소드만 출력된다 )

 

package upcasting;

class Parents{
	public void famillyName() {
		System.out.println("이");
	}
	public void name() {
		famillyName();
		System.out.println("순신");
	}
}

class Daughter extends Parents{
	public void name() {
		famillyName();
		System.out.println("국주");
	}
}

class Son extends Parents{
	public void name() {
		famillyName();
		System.out.println("기광");
	}
}

public class Ex02 {
	public static void main(String[] args) {
		/*
		Parents par = new Parents();
		par.name();
		
		Daughter d = new Daughter();
		d.name();
		
		Son s = new Son();
		s.name();
		*/
		
		
		
		// 1번 아빠이름, 2번 딸이름, 3번 아들이름
		// 번호를 선택함에 따라 해당 이름이 나오게 세팅
		Parents par;
		// Daughter d;
		// Son s;
		
		// Daugter, Son 클래스의 부모클래스가 모두 Parents로 같으니
		// 번호 선택 시 부모 클래스 변수에 자식 클래스를 객체화하여 사용 ( 메소드 오버라이딩됨 )
		int num = 3;
		if(num == 1) {
			par = new Parents();
			par.name();
		}else if(num == 2) {
			par = new Daughter();
			par.name();
		}else if(num == 3) {
			par = new Son();
			par.name();
		}
	}
}

업캐스팅 사용 예시

 

 

 

 

 

 

 

 

 

 

다운캐스팅 ( downcasting )

package upcasting;

class Test{}

public class Ex03 {
	public static void main(String[] args) {
		// 업캐스팅 ( int, String 자료형을 부모 형태의 자료형에 저장 )
		Object num = 100;
		Object name = "홍길동";
		Object t = new Test();
		System.out.println(num.getClass()); // class java.lang.Integer
		System.out.println(name.getClass()); // class java.lang.String
		
		// 컴파일 오류 발생
		// 오버라이딩이 진행되어 num 변수의 자료형이 Object 로 변경되었기 때문
		// int a = 100 + num;
		
		// 다운캐스팅 ( Object 로 업캐스팅된 num 을 int 형으로 명시하여 다운캐스팅 )
		int a = 100 + (int)num;
		System.out.println(a);
	}
}

업캐스팅된 자료를 기존의 자료처럼 사용하려면 본인의 형태로 되돌리는 다운캐스팅 과정이 필요하다

728x90

 

 

 

 

 

오버라이딩 ( Overriding )

오버라이딩

 

package overriding;

class Ferrari{
	private int ye;
	public Ferrari(int ye) {
		this.ye = ye;
	}
	public int getYe() {
		return ye;
	}
	public void speed() {
		System.out.println(ye + "년식 페라리 속도 : 300km 달립니다");
	}
	public void onCar() {
		System.out.println("자동차 시동을 켭니다!!!");
	}
}

class NewFerrari extends Ferrari{
	public NewFerrari(int ye) {
		super(ye);
	}
	public void autoSystem() {
		// 페라리를 상속받아 새로운 메소드를 추가
		System.out.println("자동 운전모드를 실행합니다!!!");
	}
	public void speed() {
		// 부모의 speed() 메소드를 오버라이딩 ( overriding )
		// 오버라이딩 할 때는 접근제한자, 반환 자료형, 메소드명을 동일하게 해야한다
		// 또한 오버라이딩을 하는 자식 클래스의 접근제한자는 부모클래스보다 크거나 같아야한다
		System.out.println("500km 까지 달릴 수 있습니다!");
	}
}

public class Ex01 {
	public static void main(String[] args) {
		NewFerrari f = new NewFerrari(2024);
		f.onCar();
		f.speed();
		f.autoSystem();
	}
}

오버라이딩 ( Overriding ) 예시

1. 오버라이딩을 할 때는 자식 클래스의 접근제한자는 부모 클래스의 접근 제한자보다 크거나 같아야 한다.

2. 오버라이딩 시 부모가 가지고 있는 메소드와 ( 접근 제한자, 반환 자료형, 메소드 이름 ) 이 동일해야 한다

 

package overriding;

import java.util.ArrayList;

class Test02 extends ArrayList<String>{
	// ArrayList 를 상속
	
	// get() 메소드 오버라이딩
	public String get(int i) {
		System.out.println( super.get(i) );
		return super.get(i);
	}
}

public class Ex02 {
	public static void main(String[] args) {
		Test02 t = new Test02();
		t.add("111");
		t.add("222");
		t.add("333");
		
		// 기존의 get() 메소드는 String 형태로 값을 반환만 해줌, 출력 X
		// get() 메소드를 오버라이딩하여 해당 값을 바로 출력하게끔 변경
		t.get(2);
		// 3 출력
	}
}

ArrayList 오버라이딩 예시

( 오버라이딩 코드에서 프린팅 값과 return 값에 super. 를 사용하지 않으면 자기 자신의 메소드가 재실행 되므로 무한으로 코드가 재실행되어 StackOverflowError 가 발생하기 때문에 super. 를 사용하여 부모 클래스의 값을 호출하여 사용한다.

 

 

 

 

 

final

package overriding;

final class Test03{
	public void test() {
		System.out.println("test03의 test 기능");
	}
}

class TestClass03 { // extends Test03 불가
	// 에러 발생 final 클래스는 상속을 받을 수 없음
	public void test() {
		System.out.println("Testclass03의 test 기능");
	}
}

public class Ex03 {
	public static void main(String[] args) {
		TestClass03 t = new TestClass03();
		Test03 t3 = new Test03();
		// final 이 붙은 클래스는 상속을 받아 사용할 수 없으므로
		// 객체화하여 사용해야 한다
		
		t3.test();
	}
}

final 을 붙이는 경우 상속, 오버라이딩 등을 변경할 수 없는 상태가 된다

위에서 만약 TestClass03 클래스가 Test03 클래스를 상속 받으려고 extends Test03 을 입력하면 컴파일 오류가 출력된다

 

package overriding;

class Test04{
	// 메소드의 접근제한자가 protected
	protected void test() {
		System.out.println("부모 실행");
	}
}

class TestClass04 extends Test04{
	// test() 메소드 오버라이딩된 상태
	// 부모 클래스의 test() 메소드가 protected 이며 오버라이딩
	// 접근제한자로 설정한 것이 public 이므로 부모의 접근제한자보다
	// 크기 때문에 오버라이딩이 가능하다
	// 만약 부모 클래스의 접근제한자보다 작다면 오버라이딩이 불가하다 ( 컴파일 오류 )
	public void test() {
		System.out.println("자식 실행");
	}
}

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

오버라이딩 시 접근제한자는 오버라이딩 하려는 부모 클래스의 메소드보다 무조건 커야한다

 

package overriding;

class TestDTO{
	String name;
	int age;
	
	// toString() 메소드를 오버라이딩
	// 저장된 공간이 출력되는 toString() 메소드는 자체로
	// 사용할 일이 많이 없기 때문에 오버라이딩하여 사용하는 경우가 많다
	@Override
	public String toString() {
		return "[name : " + name + ", age = " + age + "]";
	}
}

class Test06{
	TestDTO t;
	// 생성자
	public Test06() { t = new TestDTO(); }
	
	// 메소드
	public void setDTO() { 
		t.name = "홍길동";
		t.age = 200;
	}
	
	public void print() {
		System.out.println(t.name);
		System.out.println(t.age);
		System.out.println("------------------");
		System.out.println(t.toString());
		// 오버라이딩 전 : overriding.TestDTO@43a25848
		// 오버라이딩 후 : [name : 홍길동, age = 200]
		System.out.println(t);
		// 오버라이딩 전 : overriding.TestDTO@43a25848
		// 오버라이딩 후 : [name : 홍길동, age = 200]
	}
}

public class Ex06 {
	public static void main(String[] args) {
		Test06 t = new Test06();
		t.setDTO();
		
		t.print();
		// 오버라이딩 전 : overriding.TestDTO@43a25848
		// 오버라이딩 후 : [name : 홍길동, age = 200]
	}
}

toString() 메소드를 오버라이딩

toString 메소드는 모든 자료에 다 내재되어 있으며 해당 메소드를 사용하면 저장된 메모리 공간이 출력된다, 하지만 이 기능을 사용할 일이 없으므로 오버라이딩하여 많이 사용하며 해당 메소드 오버라이딩은 DTO 클래스에서 진행하는 경우가 많다

728x90

 

 

 

 

 

예외 처리 ( Exception )

예외 처리

 

 

package exception;

import java.util.Scanner;

public class Ex01 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int x, y, result = 0;
		System.out.print("수 입력 : ");
		x = input.nextInt();
		System.out.print("수 입력 : ");
		y = input.nextInt();
		try {
			result = x / y ;
			// try 코드에서 문제가 발생하면 catch 로 넘어간다
			// try 에서 문제가 없다면 catch 를 진행하지 않고 다음 코드로 넘어간다
		}catch(ArithmeticException e) {
			// 0 으로는 나눌 수 없는 예외를 처리
			System.out.println("문제 발생");
			System.out.println("0으로 나눌 수 없음");
		}
		System.out.println("결과 : " + result);
	}
}

발생하는 예외와 일치하는 예외로 처리해줘야 한다

( 예외 클래스들의 부모 클래스인 Exception 으로 통합하여 예외처리도 가능하다 )

 

package exception;

import java.util.Scanner;

public class Ex02 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int num;
		while(true) {
			System.out.print("수 입력 : ");
			num = input.nextInt();
			try {
				System.out.println("결과 : " + (100/num));
			} catch(Exception e) {
				// Exception 은 예외들의 부모 클래스
				System.out.println(e);
				System.err.println("에러 : " + e); // 빨간 글씨로 출력
				// java.lang.ArithmeticException: / by zero
				// 에러 : java.lang.ArithmeticException: / by zero
			}
		}
	}
}

예외 처리 예시

 

package exception;

import java.util.ArrayList;

public class Ex03 {
	public static void main(String[] args) {
		
		ArrayList<String> arr = new ArrayList<>();
		arr.add("111"); // index : 0
		arr.add("222"); // index : 1
		arr.add("333"); // index : 2
		for(int i=0; i<=arr.size(); i++) {
			// arr.size 의 크기와 같아지면 index(3) 까지 출력 명령이 들어가는데
			// 이때 해당 인덱스에 값이 없기 때문에 오류 출력
			// 이때 예외가 발생되는 문장을 콘솔창에서 찾아 try / catch 사용
			try {
				System.out.println(arr.get(i));
			} catch(IndexOutOfBoundsException e) {
				System.out.println(e);
				// java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
			}
		}
		System.out.println("다음 문장 실행!!!");
	}
}

예외 처리 예시

 

package exception;

import java.util.ArrayList;

public class Ex03 {
	public static void main(String[] args) {
		
		ArrayList<String> arr = new ArrayList<>();
		arr.add("111"); // index : 0
		arr.add("222"); // index : 1
		arr.add("333"); // index : 2
		for(int i=0; i<=arr.size(); i++) {
			// arr.size 의 크기와 같아지면 index(3) 까지 출력 명령이 들어가는데
			// 이때 해당 인덱스에 값이 없기 때문에 오류 출력
			// 이때 예외가 발생되는 문장을 콘솔창에서 찾아 try / catch 사용
			try {
				int n1 = 10, n2 = 0;
				System.out.println(n1/n2);
				
				System.out.println(arr.get(i));
			} catch(IndexOutOfBoundsException e) {
				System.out.println(e);
				// java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
			} catch(ArithmeticException e) {
				System.out.println(e);
				// java.lang.ArithmeticException: / by zero
			}
		}
		System.out.println("다음 문장 실행!!!");
	}
}

예외 처리는 오버라이드 ( override ) 를 사용하여 각자 발생하는 예외를 매개변수로 갖는 메소드로 향하게 설정이 가능하다

 

package exception;

import java.util.Scanner;

public class Ex05 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int x;
		System.out.println("수 입력");
		x = sc.nextInt();
		
		try {
			int result = 10 / x;
			System.out.println("결과 : " + result);
			return;
		}catch (Exception e) {
			// 예외가 발생된 내용을 자세하게 출력
			e.printStackTrace();
		}finally {
			// finally 는 try 가 실행되든지 catch 가 실행되든지
			// 무조건 실행되는 코드
			// return 으로 해당 코드를 종료해도 finally 는 무조건적으로 실행된다
			System.out.println("finally 실행");
			sc.close();
			// finally 를 사용하여 Scanner 스트림을 무조건 종료시키는 코드 실행
		}
		System.out.println("다음 문장들 실행!!!");
	}
}

e.printStackTrace(); - 예외의 자세한 내용을 출력

finally - 예외가 발생되던지 발생되지 않던지 해당 코드는 진행이 된다

( finally 는 try/catch 에만 사용할 수 있는 것이 아니므로 꼭 실행해야 하는 코드가 있다면 finally 처리를 해주면 된다 )

 

 

 

 

 

예외 전가

package exception;

public class Ex07 {
	public static void main(String[] args) throws InterruptedException {
										// 예외 전가를 사용하여 예외 처리
		
		// 예외처리를 해줘야 하는 Thread.sleep(); 메소드
		// 예외처리 해주지 않으면 컴파일 오류가 발생한다
		Thread.sleep(1000);
	}
}

예외 전가

 

package exception;

class Test06{
	public void test1() throws InterruptedException {
		System.out.println("1111");
		// test2() 메소드에서 예외를 전가당했으므로 예외가 발생 > throws 로 예외 전가
		test2();
	}
	public void test2() throws InterruptedException {
		System.out.println("2222");
		// 첫 예외 발생 > throws 로 예외 전가
		Thread.sleep(1000);
	}
}

public class Ex06 {
	public static void main(String[] args) throws InterruptedException {
		Test06 t = new Test06();
		// t.test1() 메소드에서 예외를 전가당했으므로 예외가 발생 > throws 로 예외 전가
		t.test1();
		// 1111
		// 2222
	}
}

예외 전가의 문제점

( 메소드를 호출하여 사용할때 해당 메소드에서 예외를 전가했다면 호출한 클래스에서도 예외를 처리해줘야 한다 )

( 만약 최초 예외가 발생된 곳에서 try / catch 로 개별로 예외를 처리해줬다면 해당 메소드를 호출해도 호출한 클래스에서는 예외가 발생하지 않는다 )

 

 

 

 

 

강제 예외

package exception;

import java.util.Scanner;

public class Ex08 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int age = 0;
		System.out.print("나이 입력 : ");
		try {
			age = sc.nextInt();
			if(age < 0) {
				throw new Exception("음수는 입력불가!!!");
			}
			
		} catch (Exception e) {
//			e.printStackTrace();
			System.out.println(e.getMessage());
		}
		System.out.println("당신의 나이는 : " + age);
	}
}

수를 음수로 입력받으면 강제로 예외로 던지는 형태

728x90

 

 

 

 

 

상속 ( Inheritance )

상속 ( Inheritance )

 

 

package inheritance;

import java.util.ArrayList;

class TestClass03 extends ArrayList<String>{
	// ArrayList 를 상속받은 TestClass03
	
	// 부모 클래스의 get 메소드를 오버라이딩
	@Override
	public String get(int index) {
		System.out.println("데이터를 가져오는 기능");
		return super.get(index);
	}
	
	// 부모 클래스의 add 메소드를 오버라이딩
	@Override
	public boolean add(String e) {
		System.out.println("데이터를 추가했습니다.");
		return super.add(e);
	} 
	
}

public class MainClass03 {
	public static void main(String[] args) {
		TestClass03 tc = new TestClass03();
		tc.add("aaa");
		// 데이터를 추가했습니다.
		
		System.out.println(tc.get(0));
		// 데이터를 가져오는 기능
		// aaa
	}
}

상속과 오버라이딩

상속 - extends 를 사용

오버라이딩 - Alt + Shift + S 후 Override/Implement Methods... 클릭

Override / Implement Methods....

 

상속을 사용한 경우와 사용하지 않은 경우의 코드 차이점 ( 상속을 사용한 경우가 더 간결한 코드로 작성이 가능하다 )

 

상속을 사용하는 이유

- 이미 만들어져 있는 클래스를 재사용하기 때문에 효율적이고 중복된 코드가 줄어든다

- 유지보수가 쉽다

- 확장성이 용이하다

- 재사용이 가능하다

- 코드가 간결해진다

 

 

 

 

 

super

package inheritance;

class Test06 {
	public void test() {
		System.out.println("부모 test 메소드");
	}
}

class TestClass06 extends Test06 {
	public void test() {
		System.out.println("자식 test 메소드");
	}
	public void display() {
		// test 메소드를 실행했을때 자기 자신에게 test 메소드가 없고
		// 부모 클래스에 test 메소드가 있다면 부모의 test 메소드를 실행한다
		
		test(); // 자식 test 메소드 출력
		this.test(); // 자식 test 메소드 출력
		super.test(); // 부모 test 메소드 출력
		
		// super : 부모 클래스를 의미
		// this  : 자기 자신 클래스를 의미
	}
}

public class MainClass06 {
	public static void main(String[] args) {
		TestClass06 tc = new TestClass06();
		tc.display();
	}
}

super 와 this

 

package inheritance;

class Test07{
	public Test07() {
		System.out.println("부모 생성자 실행");
	}
}

class TestClass07 extends Test07{
	public TestClass07() {
		System.out.println("자식 생성자 실행");
	}
}

public class MainClass07 {
	public static void main(String[] args) {
		TestClass07 tc = new TestClass07();
		// 부모 생성자 실행
		// 자식 생성자 실행
		
		// 자식을 객체화 했을때 상속받은 부모의 생성자부터 실행되며
		// 부모의 생성자가 실행된 이후 자식의 생성자가 실행된다
	}
}

상속 받을 경우 생성자의 실행 순서 ( 부모 -> 자식 )

 

package inheritance;

class Test08{
	public Test08(String s) {
		System.out.println(s + "부모 생성자 실행!!!");
	}
}

class TestClass08 extends Test08{
	public TestClass08() {
		// 부모 클래스의 생성자가 문자열을 필요로하기 때문에
		// super(); 안에 문자열을 적어 부모 클래스 생성자를
		// 호출할때 해당 값을 전달한다
		// 이때, 사용하는 super(); 는 무조건 생성자의 맨 첫 줄에
		// 적어야 한다!!!!
		super("값 전달\n");
		System.out.println("자식 생성자 실행!!!");
	}
}

public class MainClass08 {
	public static void main(String[] args) {
		TestClass08 tc = new TestClass08();
		// 값 전달
		// 부모 생성자 실행!!!
		// 자식 생성자 실행!!!
	}
}

부모 클래스의 생성자가 매개변수를 필요로 하는 경우

 

package inheritance;

class Test09{
	public Test09() {
		System.out.println("부모 기본 생성자");
	}
	public Test09(String s) {
		System.out.println(s + " : 부모 생성자");
	}
}

class TestClass09 extends Test09{
	public TestClass09() {
		System.out.println("자식 기본생성자");
	}
	public TestClass09(String s) {
		super(s);
		System.out.println(s + " : 자식 생성자");
	}
}

public class MainClass09 {
	public static void main(String[] args) {
		TestClass09 tc = new TestClass09("전달");
		// 자식 클래스로 이동 > 부모 클래스로 이동
		// super(); 를 통해 부모 클래스로 값을 전달했기 때문에
		// ( 만약 super 를 사용하지 않았다면 부모의 기본 생성자가 실행된다 )
		// 부모 클래스의 매개변수를 필요로 하는 생성자 실행 >
		// 자식 클래스의 매개변수를 필요로 하는 생성자 실행
		
		TestClass09 tc2 = new TestClass09();
		// 자식 클래스로 이동 > 부모 클래스로 이동
		// 부모 클래스의 기본 생성자 실행 > 자식 클래스의 기본 생성자 실행
		// ( 매개변수가 없기 때문에 둘 다 기본 생성자가 실행되었음 )
	}
}

부모 클래스의 매개변수를 전달하는 방법 : super();

 

 

 

 

 

private, protected

package inheritance;

class Test10{
	// 상속을 받든지 말든지 자기 자신을 제외한 모든 접근을 차단
//	private int num = 1000;
	
	// 상속받은 자식 클래스는 접근을 허용
	protected int num = 1000;
}

class TestClass10 extends Test10{
	public int num = 12345;
	public void test() {
		System.out.println("num : " + num);
		
		// 자기 자신의 변수 num 을 출력 후 없다면 부모 클래스의 num 탐색
		System.out.println("this.num : " + this.num);
		
		// 부모 클래스의 변수 num 을 탐색 -> 만약 num 변수가 없다면 컴파일 오류 발생
		System.out.println("super.num : " + super.num);
	}
}

public class MainClass10 {
	public static void main(String[] args) {
		TestClass10 tc = new TestClass10();
		tc.test();
	}
}

private 과 protected 의 차이점

 

 

 

 

 

다중 상속

package inheritance;

class A{
	public void a() {
		System.out.println("a 메소드 실행");
	}
}
class B extends A{
	// A 를 상속
	public void b() {
		System.out.println("bbbb 메소드 실행");
	}
}
class C extends B{
	// A 를 상속한 B 를 상속
	public void c() {
		System.out.println("cccccccc 메소드 실행");
	}
}

public class MainClass11 {
	public static void main(String[] args) {
		// A 를 상속한 B 를 상속한 C 를 객체로 생성
		C c = new C();
		
		// 다중 상속을 통해 A, B, C 의 모든 메소드를 사용할 수 있다
		c.a();
		c.b();
		c.c();
	}
}

중복으로 상속하는 것은 class 에서는 불가능하기 때문에 여러번에 거쳐서 상속을 진행

 

 

 

 

 

 

 

 

 

 

실습 예제

실습 예제

이전에 만들었던 로그인 프로그램을 찾지 못하는 연유로 처음부터 코딩.....

 

package inheritance;

public class MainLogIn {
	public static void main(String[] args) {
		
		LogInService ls = new LogInService();
		while(true) {
			ls.mainPrint();
		}
	}
}

MainLogIn 클래스

 

package inheritance;

import java.text.SimpleDateFormat;
import java.util.Scanner;

public class LogInService extends java.util.Date {
	Scanner sc = new Scanner(System.in);
	LogInDTO DTO = new LogInDTO();
	
	// 메인 메뉴
	public void mainPrint() {
		System.out.println("1. 로그인");
		System.out.println("2. 회원가입");
		System.out.println("3. 탈퇴");
		System.out.print(">>> : ");
		int choice = sc.nextInt();
		
		switch(choice) {
		case 1 : logIn(); break;
		case 2 : createId(); break;
		case 3 : removeId(); useTime(); break;
		default :
			System.out.println("입력 오류!!!");
			break;
		}
	}
	
	// 로그인
	private void logIn() {
		if(DTO.getId() == null) {
			System.out.println("회원 등록부터 진행하세요!");
		}
		else {
			System.out.print("아이디를 입력 : ");
			String id = sc.next();
			System.out.print("비밀번호를 입력 : ");
			String pwd = sc.next();
			
			checkId(id, pwd);
		}
	}
	
	// 로그인 시 아이디 검증
	private void checkId(String id, String pwd) {
		if(DTO.getId().equals(id) && DTO.getPwd().equals(pwd)) {
			System.out.println("!!! " + id + "님 로그인 완료 !!!");
			// 로그인 완료 시 시간 저장
			DTO.setStartTime(System.currentTimeMillis());
		}
		else System.out.println("회원정보가 올바르지 않습니다");
	}
	
	// 회원 생성
	private void createId() {
		if(DTO.getId() == null) {
			System.out.print("아이디 입력 : ");
			String id = sc.next();
			System.out.print("비밀번호 입력 : ");
			String pwd = sc.next();
			
			DTO.setId(id);
			DTO.setPwd(pwd);
			System.out.println("회원가입이 완료되었습니다!");
		}else {
			System.out.println("이미 회원이 존재합니다. 삭제 후 진행하세요");
		}
	}
	
	// 회원 삭제
	private void removeId() {
		DTO.setId(null);
		DTO.setPwd(null);
		System.out.println("회원 탈퇴가 완료되었습니다!!!");
		
		// 회원 삭제 시간 저장
		DTO.setEndTime(System.currentTimeMillis());
	}
	
	// 로그인 시간, 탈퇴 시간, 사용 시간 출력
	private void useTime() {
		SimpleDateFormat si = new SimpleDateFormat("yyyy년 MM월 dd일 aa hh시 mm분 ss초");
		System.out.println("시작 시간 : " + si.format(DTO.getStartTime()));
		System.out.println("종료 시간 : " + si.format(DTO.getEndTime()));
		System.out.println("사용 시간 : " + ((DTO.getEndTime()-DTO.getStartTime()) / 1000) + "초");
	}
}

LogInService 클래스

( java.util.Date 클래스를 상속받아 사용 날짜에 대한 정보를 저장 및 출력 )

 

package inheritance;

public class LogInDTO {
	private long startTime, endTime;
	private String id, pwd;
	
	// getter / setter
	public long getStartTime() {
		return startTime;
	}
	public void setStartTime(long startTime) {
		this.startTime = startTime;
	}
	public long getEndTime() {
		return endTime;
	}
	public void setEndTime(long endTime) {
		this.endTime = endTime;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
}

LogInDTO 클래스

 

 

 

 

 

 

코드 실행
728x90

 

 

숫자 야구

 

 

package com.baseball;

public class Main {
	public static void main(String[] args) {
		while(true) {
			BaseballService bb = new BaseballService();
			int choice = bb.mainPrint();
			bb.choiceNum(choice);
		}
	}
}

Main 클래스

 

package com.baseball;

import java.io.IOException;
import java.util.Random;
import java.util.Scanner;

public class BaseballService {
	Scanner sc = new Scanner(System.in);
	BaseballDTO DTO = new BaseballDTO();
	Random ran = new Random();
	
	public int mainPrint() {
		System.out.println("★★★★★ 숫자 야구 ★★★★★★");
		System.out.println("★   1. 숫자 야구 플레이   ★");
		System.out.println("★   2. 종         료     ★");
		System.out.println("★★★★★★★★★★★★★★★★★★");
		System.out.print("번호 입력 >>> ");
		int choice = sc.nextInt();
		return choice;
	}
	
	public void choiceNum(int choice) { 
		switch(choice) {
		case 1 : mainGame(); break;
		case 2 : 
			System.out.println("프로그램을 종료합니다");
			break;
		default :
			System.out.println("입력 오류 발생!!! 프로그램을 다시 실행하시오");
			break;
		}
	}
	
	public void mainGame() {
		// 콘솔창 지우기
		erasePrint();
		// 숫자 야구 정답 생성 - DTO 클래스의 mainBall 에 저장
		makeMainBall();
		// 숫자 생성부분 시각화
		makeView();
		
		while(true) {
			System.out.println("★★★★★★★★★★★");
			System.out.println("★수를 예상하세요★");
			System.out.println("★    ex)0125   ★");
			System.out.println("★★★★★★★★★★★");
			System.out.println("현재 도전 횟수 : " + DTO.getTryNum());
			System.out.print("입력 >>> ");
			String guessBall = sc.next();
			try{
				if(Integer.parseInt(guessBall) > 0 && Integer.parseInt(guessBall) < 10000) {
					// 추측한 숫자를 guessBall 변수로 생성자를 통해 세팅
					DTO.setGuessBall(guessBall.charAt(0), guessBall.charAt(1), guessBall.charAt(2), guessBall.charAt(3));
					checkBall();
					System.out.println("--- 추측 결과 ---");
					System.out.println("   Strike : " + DTO.getStrike());
					System.out.println("   Ball   : " + DTO.getBall());
					System.out.println("----------------");
					
					System.out.println("다시 게임을 준비하는중.............");
					
					timeSleep(5000);
					
					// 정답을 맞춘 경우
					if(DTO.getStrike() == 4) {
						System.out.println("☆★☆★숫자를 모두 맞추셨습니다★☆★☆");
						System.out.println("☆★ 총 도전 횟수 : " + DTO.getTryNum() + " ★☆");
						System.out.printf("정 답 : %d %d %d %d\n",DTO.getMainBall(0), DTO.getMainBall(1), DTO.getMainBall(2), DTO.getMainBall(3));
						break;
					}
					
					// 스트라이크와 볼 갯수 초기화
					DTO.setBall(0); DTO.setStrike(0);
					// 도전 횟수 증가
					DTO.setTryNum(DTO.getTryNum() + 1);
					
				}else {
					System.out.println("!!!입력 오류!!!");
					continue;
				}
			} catch(Exception e){
				System.out.println("!!!입력 오류!!!");
				continue;
				}
			
			
		}
		
	}
	
	// 콘솔 창 지우개
	public void erasePrint() {
		for(int i=0; i<=100; i++) System.out.println();
	}
	// 정답 생성
	public void makeMainBall() {
		int[] num = new int[4];
		for(int i=0; i<4; i++) {
			num[i] = ran.nextInt(10);
			for(int j=0; j<i; j++) {
				if(num[i] == num[j]) i--;
			}
		}
		DTO.setMainBall(num[0], num[1], num[2], num[3]);
	}
	// a 초 만큼 코드 중지
	public void timeSleep(int a) {
		try {
			Thread.sleep(a);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	// 난수 생성 시각화
	public void makeView() {
		for(int i=1; i<=4; i++) {
			System.out.println("★★★★★★★★★★★★★★★★★★");
			System.out.printf("★★★★%d번째 수 생성중★★★★\n", i);
			timeSleep(1000);
			for(int j=0; j<=7; j++)
				System.out.println("★★★★★★★★★★★★★★★★★★");
				timeSleep(500);
		}
		System.out.println("★★★★★★준비  완료★★★★★★");
		System.out.println();
	}
	// Strike 와 Ball 갯수 체크
	public void checkBall() {
		for(int i=0; i<4; i++) {
			if (DTO.getGuessBall(i) == DTO.getMainBall(i)) {
				DTO.setStrike(DTO.getStrike() + 1);
			}
			for(int j=0; j<4; j++) {
				if(DTO.getGuessBall(i) == DTO.getMainBall(j)) {
					DTO.setBall(DTO.getBall() + 1);
				}
			}
		}
	}
}

BaseballService 클래스

 

package com.baseball;

import java.util.ArrayList;

public class BaseballDTO {
	// 숫자 야구 정답
	private int[] mainBall = new int[4];
	// 추측 숫자
	private int[] guessBall = new int[4];
	// 정답이면 true, 정답이 아니면 false
	private boolean ballCheck = false;
	// 도전 횟수, ball, strike
	private int tryNum = 0, ball = 0, strike = 0;
	
	public BaseballDTO() {}
	
	public int getMainBall(int i) {
		return mainBall[i];
	}
	public void setMainBall(int num1, int num2, int num3, int num4) {
		this.mainBall[0] = num1;
		this.mainBall[1] = num2;
		this.mainBall[2] = num3;
		this.mainBall[3] = num4;
	}
	public boolean isBallCheck() {
		return ballCheck;
	}
	public void setBallCheck(boolean ballCheck) {
		this.ballCheck = ballCheck;
	}
	public int getTryNum() {
		return tryNum;
	}
	public void setTryNum(int tryNum) {
		this.tryNum = tryNum;
	}
	public int getGuessBall(int i) {
		return guessBall[i];
	}
	public void setGuessBall(char num1, char num2, char num3, char num4) {
		this.guessBall[0] = Character.getNumericValue(num1);
		this.guessBall[1] = Character.getNumericValue(num2);
		this.guessBall[2] = Character.getNumericValue(num3);
		this.guessBall[3] = Character.getNumericValue(num4);
	}
	public int getBall() {
		return ball;
	}
	public void setBall(int ball) {
		this.ball = ball;
	}
	public int getStrike() {
		return strike;
	}
	public void setStrike(int strike) {
		this.strike = strike;
	}	
}

BaseballDTO 클래스

 

 

 

 

- 메모 -

1. 코드를 더 깔끔하게 정리하여 작성할 수 있는 방법이 무엇인지 생각하기

2. 현재 작성한 코드에 중복된 코드가 무엇인지, 추후에 공부하면서 보완할 내용은 무엇인지 꾸준하게 생각하기

3. web 또는 Unity 를 활용하여 게임을 실제 시각화하여 서비스해보기

728x90

 

 

 

 

 

실습

미니 실습

 

package constructor;

public class MainClass {
	public static void main(String[] args) {
		TimeService ts = new TimeService();
		ts.display();
	}
}

MainClass 클래스

 

package constructor;

import java.text.SimpleDateFormat;
import java.util.Scanner;

public class TimeService {
	Scanner sc = new Scanner(System.in);
	TimeDTO DTO = new TimeDTO();
	SimpleDateFormat si = new SimpleDateFormat("yyyy년 MM월 dd일 aa hh시 mm분 ss초");
	String startTime, endTime;
	int useTime;
	
	// 기본 메뉴 출력
	public void display() {
		while(true) {
			System.out.println("1. 시작 시간 설정");
			System.out.println("2. 시작 시간 확인(년 월 일 시 분 초)");
			System.out.println("3. 종료 시간 설정");
			System.out.println("4. 종료 시간 확인(년 월 일 시 분 초)");
			System.out.println("5. 사용 시간 가져오기");
			System.out.print("선택 >>> ");
			int choice = sc.nextInt();
			
			switch(choice) {
			case 1: startTime(); break;
			case 2: showStart(); break;
			case 3: endTime(); break;
			case 4: showEnd(); break;
			case 5: useTime(); break;
			default : System.out.println("입력 오류!!!\n"); break;
			}
		}
	}
	// 시작 시간 설정
	private void startTime() {
		DTO.setStartTime(System.currentTimeMillis());
		System.out.println("시작 시간 설정 완료");
	}
	// 시작 시간 출력
	private void showStart() {
		startTime = si.format(DTO.getStartTime());
		System.out.println("시작 시간 : " + startTime);
	}
	// 종료 시간 설정
	private void endTime() {
		DTO.setEndTime(System.currentTimeMillis());
		System.out.println("종료 시간 설정 완료");
	}
	// 종료 시간 출력
	private void showEnd() {
		endTime = si.format(DTO.getEndTime());
		System.out.println("종료 시간 : " + endTime);
	}
	// 사용 시간 출력
	private void useTime() {
		// 시작시간이 종료시간보다 빠른 경우
		if ( DTO.getEndTime() < DTO.getStartTime() ) {
			System.out.println("시작 시간이 종료시간보다 빠를 수 없습니다.");
		}
		// 시작 시간이 설정되지 않은 경우
		else if ( DTO.getStartTime() == 0 ) {
			System.out.println("시작 시간을 설정해주세요");
		}
		// 종료 시간이 설정되지 않은 경우
		else if ( DTO.getEndTime() == 0 ) {
			System.out.println("종료 시간을 설정해주세요");
		}
		// 사용 시간 계산 후 출력
		else {
			double use = DTO.getEndTime() - DTO.getStartTime();
			useTime = (int)(use / 1000);
			System.out.println("사용 시간 : " + useTime + "초");
		}
	}
}

TimeService 클래스

 

package constructor;

public class TimeDTO {
	private long startTime, endTime;
	
	public long getStartTime() {
		return startTime;
	}
	public void setStartTime(long startTime) {
		this.startTime = startTime;
	}
	public long getEndTime() {
		return endTime;
	}
	public void setEndTime(long endTime) {
		this.endTime = endTime;
	}
}

TimeDTO 클래스

 

 

코드 실행
728x90

 

 

 

 

 

실습

미니 실습

 

package constructor;

public class MemberMain {
	public static void main(String[] args) {
		MemberService mem = new MemberService();
		mem.display();
	}
}

MemberMain 클래스

 

package constructor;

import java.util.Scanner;

public class MemberService {
	Scanner sc = new Scanner(System.in);
	MemberDTO DTO = new MemberDTO();
	
	// 메인 메뉴 출력
	public void display() {
		
		while(true) {
			System.out.println("=== 학생관리 프로그램 ===");
			System.out.println("     1. 학생 등록");
			System.out.println("     2. 학생 보기");
			System.out.println("     3. 정보 수정");
			System.out.println("     4. 회원 탈퇴");
			System.out.println("========================");
			System.out.print("번호를 선택하세요 >>> ");
			
			int choice = sc.nextInt();
			
			switch(choice) {
			case 1 : createStd(); break;
			case 2 : showStd(); break;
			case 3 : changeStd(); break;
			case 4 : removeStd(); break;
			default : 
				System.out.println("!!!입력 오류!!!");
				break;
			}
		}
	}
	
	// 학생 정보 입력
	private void createStd() {
		System.out.print("이름 입력 >>> ");
		String name = sc.next();
		System.out.print("국어 성적 입력 : ");
		int kor = sc.nextInt();
		System.out.print("영어 성적 입력 : ");
		int eng = sc.nextInt();
		System.out.print("수학 성적 입력 : ");
		int math = sc.nextInt();
		
		DTO = new MemberDTO(name, kor, eng, math);
		int sum = getSum(kor, eng, math);
		char grade = getGrade(getSum(kor, eng, math));
		DTO.setSum(sum);
		DTO.setGrade(grade);
	}
	
	// 합 구하기
	private int getSum(int kor, int eng, int math) {
		return (kor + eng + math);
	}
	
	// 평균 구하기
	private char getGrade(int sum) {
		double aver = sum/3.0;
		if (aver >= 90) return 'A';
		else if (aver >= 80) return 'B';
		else return 'c';
	}
	
	// 학생 정보 출력
	private void showStd() {
		
		if ( DTO.getName() != null) {
			System.out.println("========= 학생 정보 =========");
			System.out.println("이름 : " + DTO.getName());
			System.out.println("국어 : " + DTO.getKor());
			System.out.println("영어 : " + DTO.getEng());
			System.out.println("수학 : " + DTO.getMath());
			System.out.println("합 : " + DTO.getSum());
			System.out.println("등급 : " + DTO.getGrade());
			System.out.println("============================");
			System.out.println();
		}
		else System.out.println("학생 정보를 등록 후 이용하세요.\n");
	}
	
	// 점수 변경
	private void changeStd() {
		if (DTO.getName() != null) {
			System.out.println("\n===== 정보 수정 =====");
			System.out.println("1. 이름 수정");
			System.out.println("2. 국어 점수 수정");
			System.out.println("3. 영어 점수 수정");
			System.out.println("4. 수학 점수 수정");
			System.out.println("====================");
			System.out.print("선택하세요 >>> ");
			int choice = sc.nextInt();
			
			switch(choice) {
			case 1 : changeName(); break;
			case 2 : changeKor(); break;
			case 3 : changeEng(); break;
			case 4 : changeMath(); break;
			case 5 : 
				System.out.println("!!! 입력 오류 !!!\n");
				break;
			}
			
			System.out.println("!!! 변경 완료 !!!\n");
			DTO.setSum(DTO.getKor() + DTO.getEng() + DTO.getMath());
			DTO.setGrade(getGrade(DTO.getSum()));
		}else System.out.println("학생 정보를 등록 후 이용하세요.\n");
	}
	
	// 이름 변경
	private void changeName() {
		System.out.print("변경할 이름 입력 : ");
		String name = sc.next();
		DTO.setName(name);
	}
	
	// 국어 변경
	private void changeKor() {
		System.out.print("국어 점수 입력 : ");
		int kor = sc.nextInt();
		DTO.setKor(kor);
	}
	
	// 영어 변경
	private void changeEng() {
		System.out.print("영어 점수 입력 : ");
		int eng = sc.nextInt();
		DTO.setMath(eng);
	}
	
	// 수학 변경
	private void changeMath() {
		System.out.print("수학 점수 입력 : ");
		int math = sc.nextInt();
		DTO.setMath(math);
	}
	
	// 학생 탈퇴
	private void removeStd() {
		if(DTO.getName()!=null) {
			DTO = new MemberDTO();
			System.out.println("!!!회원정보 초기화 완료!!!\n");
		} else System.out.println("등록된 회원이 없습니다.\n");
	}
}

MemberService 클래스

 

package constructor;

public class MemberDTO {
	private String name;
	private int kor, eng, math, sum;
	private char grade;
	public String getName() {
		return name;
	}
	
	public MemberDTO(String name, int kor, int eng, int math){
		this.name = name;
		this.kor = kor;
		this.eng = eng;
		this.math = math;
	}
	
	public MemberDTO() {}
	
	// getter / setter 생성
	public void setName(String name) {
		this.name = name;
	}
	public int getKor() {
		return kor;
	}
	public void setKor(int kor) {
		this.kor = kor;
	}
	public int getEng() {
		return eng;
	}
	public void setEng(int eng) {
		this.eng = eng;
	}
	public int getMath() {
		return math;
	}
	public void setMath(int math) {
		this.math = math;
	}
	public int getSum() {
		return sum;
	}
	public void setSum(int sum) {
		this.sum = sum;
	}
	public char getGrade() {
		return grade;
	}
	public void setGrade(char grade) {
		this.grade = grade;
	}
}

MemberDTO 클래스

 

 

 

 

코드 실행
728x90

 

 

 

 

 

Default 접근 제한자

패키지를 분리

 

 

private 과 public 의 접근제한자가 붙지 않은 클래스나 메소드의 경우 같은 패키지 내에서는 접근이 가능하나 같은 프로젝트 안이라도 패키지가 분리되어 있다면 접근이 불가하다

접근제한자가 붙지 않은 것을 default 라고 부른다

728x90

+ Recent posts