객체 지향 중급 문법

 

상속

 

다형성

 

추상화 / 인터페이스

 

캡슐화


문법 - 알고리즘 - 디자인패턴(경험으로 만들어진 지식)

//시험

1. 서술형 ex.메서드가 뭔지 설명하시오(틀리면 감점, 상대적으로 너무 짧아도 감점)

2. 문제해결 시나리오 (어떤 에러인지 말하고 해결하려면 어떻게 하면 되는지)

3. 평가자 체크 리스트 (코드짜기 Yes/No 부분점수 없음, 이클립스를 허용하는 상황도 있고 못쓸수도 있음, 웹서핑+기존 워크스페이스 등은 사용 못함)

//요번주 시험은 서술형 1번+평가자체크리스트 1번 > 과락(40점 이하)없이 평균 60점, 이상 통과

 


public class Silver {

	private int id;
	private String name;
	private int point;
	
	public Silver(int id, String name, int point) {
		this.id = id;
		this.name = name;
		this.point = point;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPoint() {
		return point;
	}
	public void setPoint(int point) {
		this.point = point;
	}
	
}
//mvc 패턴으로 제작
//main은 프론트 화면만
public class Manager {

	private Silver[] members = new Silver[10]; // 인스턴스는 0개, 인스턴스를 저장할수 있는 실버형 변수 10개
	
	//스텍: 메니저 참조변수(인스턴스주소)
	//힙: 매니저 인스턴스 (멤버스라는 배열의 주소를 가진 참조변수) // 
	
	private int index = 0 ; // 지역변수로 놓으면 실행될때 마다 0으로 초기화,  멤버필드로 만들기
	
	public void addMember(Silver s) {  //주소를 받아서  배열의 0번칸에 담아라
		
		members[0] = s;
		
	}
	public void printMember() {}
	
}
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		//메인은 프론트데스크 -> 정보는 전산팀에서
		Manager manager = new Manager(); // 매니저 인스턴스 생성
		Scanner sc = new Scanner(System.in);
		System.out.println("=== 회원 관리 시스템 ===");
		System.out.println("1. 신규 회원 등록");
		System.out.println("2. 회원 목록 출력");
		System.out.println("3. 종료");
		System.out.println("> ");
		
		String menu = sc.nextLine();
		
		if(menu.contentEquals("1")) {
			//입력받는 기능은 Manager에 넣는가? Main화면에 넣는가? -> 범용성, 재활용성 고려
			// 다른 프로젝트(콘솔 입력외에 입력방식)에 Manager 클래스를 옮겼을때 그내로 활용할 수 있도록
			
			
			System.out.println("회원번호 : ");
			int id = Integer.parseInt(sc.nextLine());

			System.out.println("회원이름 : ");
			String name = sc.nextLine();

			System.out.println("포인트 : ");
			int point = Integer.parseInt(sc.nextLine());
			
			
			
			manager.addMember(new Silver(id, name, point));
			
		}else if(menu.contentEquals("2")) {
			manager.printMember();
		}else if(menu.contentEquals("3")) {
			System.out.println("시스템을 종료합니다.");			
			System.exit(0);
		}else {
			System.out.println("메뉴를 다시 학인해주세요.");
			
		}
		
	}

}

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		Manager manager = new Manager(); 
스텍

[ ] Manager manager

(힙메모리에 멤버스/인덱스 가르킴)

   

new Manager

members(배열 0번째 칸을 가르킴)

 

sliver형 변수

[ ][ ][ ][ ][ ][ ][ ][ ][ ][ ]

  index  
       

new 오른쪽이 인스턴스

기본자료형이면서 메서드 안에 있어야 Stack

멤버필드는 메서드 밖에

힙메모리 안에 쉐어드풀(스트링상수전용) 공간 있음  //지금하는 코드와는 무관


public class Manager {

	private Silver[] members = new Silver[10];
	
	private int index = 0 ; 
	
	public void addMember(Silver s) {  
		
       // addMember Stack( 매개변수 Silver s있음)
       // Stack은 건초처럼 위로 쌓아가게 그림
       
		members[index++] = s;
        //멤버스 변수의 0번째 칸이 주소를 가르킴
		
	}
			

 

모든 매서드 콜은 스텍 메모리를 만든다.

순간적으로 만들어졌다 지워짐

 

main 매서드의 지역변수들은 거의 안지워짐 (메인매서드가 프로그램 자체이기 때문에)


골드 멤버쉽 추가된 경우

public class Gold {
	
	private int id;
	private String name;
	private int point;
	
	
	public Gold() {}
	public Gold(int id, String name, int point) {
		super();
		this.id = id;
		this.name = name;
		this.point = point;
	}

	public double getBonus() {
		return this.point*0.03;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPoint() {
		return point;
	}
	public void setPoint(int point) {
		this.point = point;
	}
	
}
//mvc 패턴으로 제작
//main은 프론트 화면만
public class Manager {

	private Silver[] silverMembers = new Silver[10]; 

	private Gold[] goldMembers = new Gold[10]; 

	private int silverIndex = 0 ; 
	private int goldIndex = 0 ; 


	public void addMember(Silver s) {  

		silverMembers[silverIndex++] = s;

	}

	public void addMember(Gold s) {  // 오버로딩, 매서드이름같아도 매개변수가 다르면 다르다!

		goldMembers[goldIndex++] = s;

	}

	public void printMember() {
		System.out.println("=== 회원 목록 ===");
		System.out.println("아이디\t이름\t포인트\t보너스");

		for(int i=0; i< goldIndex ; i++) {
			System.out.println(goldMembers[i].getId()+"\t"
					+goldMembers[i].getName()+"\t"
					+goldMembers[i].getPoint()+"\t"
					+goldMembers[i].getBonus());
		}
		
		for(int i=0; i< silverIndex ; i++) {
			System.out.println(silverMembers[i].getId()+"\t"
					+silverMembers[i].getName()+"\t"
					+silverMembers[i].getPoint()+"\t"
					+silverMembers[i].getBonus());
		}

	}

}
import java.util.Scanner;

public class Main {

	public static void main(String[] args) {

		//메인은 프론트데스크 -> 정보는 전산팀에서
		Manager manager = new Manager(); // 매니저 인스턴스 생성
		Scanner sc = new Scanner(System.in);

		while(true){
			System.out.println("=== 회원 관리 시스템 ===");
			System.out.println("1. 신규 회원 등록");
			System.out.println("2. 회원 목록 출력");
			System.out.println("3. 종료");
			System.out.print("> ");

			String menu = sc.nextLine();

			if(menu.contentEquals("1")) {
				//입력받는 기능은 Manager에 넣는가? Main화면에 넣는가? -> 범용성, 재활용성 고려
				// 다른 프로젝트(콘솔 입력외에 입력방식)에 Manager 클래스를 옮겼을때 그내로 활용할 수 있도록

				manager.addMember(new Silver(1001, "Jack", 1000));
				manager.addMember(new Silver(1002, "Tom", 2000));
				manager.addMember(new Silver(1003, "Jane", 3000));
				manager.addMember(new Gold(1004, "Susan", 4000));

			}else if(menu.contentEquals("2")) {

				manager.printMember();

			}else if(menu.contentEquals("3")) {
				System.out.println("시스템을 종료합니다.");			
				System.exit(0);
			}else {
				System.out.println("메뉴를 다시 학인해주세요.");

			}

		}

	}

}

> 비효율적 (다음 멤버쉽이 추가되면? 기능이 많은 경우는?)

 

  • 현재 작성한 회원 관리 시스템의 Critical한 문제점 3가지
    1. 코드 중복도 문제
      • > (Silver , Gold, ....) > 상속(IS-A) 문법으로 해결
    2. 클래스간 결합도 문제
      • > (Silver & Manager, ... ) > 의존도가 높다, 하나의 클래스가 빠지면 기능 못함, 클래스간 결합도가 낮을수록 좋다. > 다형성 문법으로 해결
    3. 저장소 문제
      • (회원이 10명 넘으면 에러, 처음부터 크게 값을 잡아 놓으면 용량을 많이 차지) > Collection Framework로 해결

  • 상속
    • Class 간의 관계
    • has-a
// 클래스간 관계 : Has-a 포함 관계
// A has a B : A가 B를 가진다
public class Police {
	private Gun gun = new Gun(); //포함관계 Police has a Gun
}
public class Gun {

}

IS-A


//골드클래스는 멤버클래스를 확장한다.
//Member는 부모클래스, 상위클래스, super class
//Gold는 하위클래스, 자식클래스, derived class

//오류 발생 
public class Silver extends Member{

	public Silver(int id, String name, int point) {
		this.id = id; //The field Member.id is not visible
		this.name = name; //The field Member.id is not visible
		this.point = point; //The field Member.id is not visible
        
//접근제한자를 건드리면 정보은닉을 부분적으로 잃음
//1. private > public 정보은닉을 못함, 안좋은 방법
//2. protected > 상속일 때는 public처럼 쓰임
//3. 안쓰면 패키지 
	}
	
}
//setter 사용
public class Silver extends Member{

	public Silver(int id, String name, int point) {
		this.setId(id); 
		this.setName(name);
		this.setPoint(point);

	}
	
}

public class Silver extends Member{
	
	public Silver(int id, String name, int point) {
		super(id,name,point); // 지워도 존재, 상위클래스의 생성자를 부른다.
		//인자값 전달을 위해 사용
	
	}
	
}
public class Member {


	private int id;
	private String name;
	private int point;
	
	
	public Member(int id, String name, int point) {
		this.id =id;
		this.name =name;
		this.point =point;
	}

	public double getBonus() {
		return this.point*0.03;
	}

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPoint() {
		return point;
	}
	public void setPoint(int point) {
		this.point = point;
	}
	
}
public class Gold extends Member{
/*
Implicit super constructor Member() is undefined for default constructor.
Must define an explicit constructor
*/
}

//Construct Member() 가 사라짐

> 골드 생성자를 명시

> Member class에 오버로딩 >> 오류는 사라지지만 값이 초기화 되지 않음

 

public class Gold extends Member{

	public Gold(int id, String name, int point) {
		super(id, name, point);
	}
}

 

Silver 보너스 비율을 다르게 만들기!

 

override Member.getBonus //무효화시키다

Method overrride // 상속받은 매서드를 재정의
실버클래스 getBonus()를 재정의


override 보다 더 좋은 방법

Member getBonus() 에서 리턴을 하면 안된다

>void로 만들면 오버라이드한 것들 다 작동안함

>>중괄호 지우고 세미콜론 넣기

This method requires a body instead of a semicolon

설계목적으로 만들어진 코드라고 명시

> 아예 지우고 하위클래스에서 오버라이드 대신 각각 코드를 쓰지 않는 이유 > 묶어놨을 때의 이점 있음

 

abstract / 자바야 설계목적의 코드이므로 토달지 말고 실행해라!

설계목적이라면서 콜해버리면 어떻게함?

//설계목적이라면서 콜해버리면 어떻게함?
//클래스에도 abstract 달기, 추상클래스로 만들기 
//추상클래스는 new가 안됨 > 인스턴스 못만듦 > call 될 수 없음

abstract public class Member {

	private int id;
	private String name;
	private int point;

	public Member(int id, String name, int point) {
		this.id =id;
		this.name =name;
		this.point =point;
	}

	abstract public double getBonus();


	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPoint() {
		return point;
	}
	public void setPoint(int point) {
		this.point = point;
	}

}

implements

//다시 에러 발생, 상위클래스의 추상 메서드를 받을수 없어서
//내용을 채워줘야함
//추상 메서드를 상속 받을 때에는 implements 필수
//(추상 메서드에서는 오버라이드라고 하지 않음) 
public class Gold extends Member{

	public Gold(int id, String name, int point) {
		super(id, name, point);
	}
	public double getBonus() {
		return this.getPoint()* 0.03;
	}
}

call back 패턴

 


다형성

class A{	
}
class B{	
}
//퍼블릭 클래스는 하나만
//퍼블릭이 아닌 클래스는 한 파일에 여러개여도 오류가 나지는 않음
//하지만, 파일 하나당 클래스 하나가 적절
public class Poly {
	public static void main(String[] args) {
		//다형성, 형태가 많은 성질
		//변수 하나가 여러가지 (참조)자료형을 담을 수 있는 상태
		
		A a = new B();		//Type mismatch: cannot convert from A to B
		B b = new A();		//Type mismatch: cannot convert from A to B

		//참조 자료형 간에 상속 관계에 놓였을때 허용
	}
}
class A{	
}
class B extends A{	
}

public class Poly {
	public static void main(String[] args) {
		//다형성, 형태가 많은 성질
		//변수 하나가 여러가지 (참조)자료형을 담을 수 있는 상태
		
		A a = new B();
		B b = new A();		//Type mismatch: cannot convert from A to B

		//상위클래스의 참조변수는 자신을 상속 받는 하위클래스의 인스턴스를 저장 할 수 있다
	}
}

상위클래스의 참조변수는 자신을 상속 받는 하위클래스의 인스턴스를 저장 할 수 있다

그렇다면 a는 A로 동작할까 B로 동작할까?

B형 인스턴스 범위가 A보다 더 크다 (A를 상속 받고 확장)

기본적으로는 상위 인스턴스의 기능 사용

B형이라고 생각한다면 A,B 기능 둘다 사용 할 수 있다.

B형 인스턴스를 담을 수는 있지만 B형의 기능은 못쓴다?

B로 다운캐스팅하면 B의 기능도 쓸 수 있다.

다운캐스팅하면 상위, 하위 기능 모두 사용 가능

예외적으로 down casting 없이 하위 인스턴스 사용하는 경우

물려받은걸 오버라이드 한 경우, down casting없이 하위클래스 기능 사용 가능

  • 다형성의 장점
    1. 모듈화 코드 작성 유리
    2. 코드 결합도를 낮추는 용도
    3. 편의성

//다형성 활용 예
public class Manager {

	private Member[] members = new Member[10];
	//member는 추상클래스 > 인스턴스를 만들 수 없다 .
	//지금 이 코드는 멤버 인스턴스를 만든게 아니라 멤버형 변수를 만든 것 

	private int index = 0 ;

	public void addMember(Member m) {  //up casting되어 
		members[index++] = m;		// member형으로 저장
	}


	public void printMember() {
		System.out.println("=== 회원 목록 ===");
		System.out.println("아이디\t이름\t포인트\t보너스");

		for(int i=0; i< index ; i++) {
			System.out.println(members[i].getId()+"\t"
					+members[i].getName()+"\t"
					+members[i].getPoint()+"\t"//멤버의기능(getId,getName,getPoint)만 볼수 있음
					+members[i].getBonus()); //getBonus추상메서드가 implements된 값 나옴

		}

	}

}

 


암묵적 

자바에 존재하는 모든 class는 상속을 받게 되어있다

기능을 만들지 않아도 기본적으로 나오는 기능들은 Object에서 상속 받은 것들이다.

class A extends Object{	//자바의 모든 class는 암묵적으로 extends Object 상속받음
						// A is a Object : A는 객체이다
						// Object는 모든 클래스의 최고 조상	
}
class B extends A{	
	
}
public class Poly {
	public static void main(String[] args) {
		//다형성

		A a = new A();
		a.  //
		
	}
}

- Object (근원지) // func() (A가 근원지)

import java.util.Scanner;

class A {
	public void func () {};
}	
class B extends A{	
	
}
class C extends B{	//다중 상속, 자식이 아니라 자손
	
}// 모든 클래스는 어떤 방식이던 Object를 상속 (보이진 않지만)

public class Poly {
	public static void main(String[] args) {
		//다형성

		Object o1 = new Object();
		Object o2 = new Scanner(System.in);
		Object o3 = new A();
		Object o4 = new Silver(1006, "ABC", 1000);
		Object o5 = 10; // new Integer(10); //auto boxing
		//Object는 모두 담을 수 있다.
		//기본형은 상속받는 건 아니지만 auto boxing(자동 형변환)일어남, 몇몇 참조변수만 허용
		
		//Wrapper Class //시험내기 좋다.
//		int Integer
//		float Float
//		double Double
//		boolean Boolean
		
		
	}
}

 

+ Recent posts