Skip to content

Latest commit

 

History

History
591 lines (417 loc) · 14.7 KB

06장 (객체와 클래스).md

File metadata and controls

591 lines (417 loc) · 14.7 KB

6장 (객체와 클래스)

6.1 클래스 정의

개체 : 인간이 관념적으로 인식한 것을 S/W로 구체화 한 것 속성(변수,필드) : 개체가 갖고 있는 값 메서드(함수) : 개체가 할수 있는 동작 이벤트 : 개체가 반응을 할수 있게 외부에서 가해지는 자극


6.2 객체와 클래스

  • 클래스 : 객체의 형태를 정의(설계도) 객체(인스턴스) : 클래스를 기반으로 생성된(메모리에 할당된) 것

6.3 클래스 정의

class 클래스명 { 속성 정의 생성자 정의 매서드 정의 }

  • 클래스명은 소스파일명과 동일해야 한다.

6.4 객체 생성과 클래스 변수

클래스 변수(참조형 변수) : 생성된 인스턴스를 지정할 변수 클래스명 변수명; Ex> SportsCar car;

  • 클래서 변수 선언과 동시에 인스턴스를 생성 클래스명 변수명 = new 클래스명(인수, 인수,...); Ex> SportsCar car = new SportsCar();

6.5 클래스의 구성 맴버

  • 필드(속성, 변수) : 클래스의 상태값을 저장하는 변수
  • 생성자(메서드) : new 연산자를 통해 객체가 생성될 때 최초로 동작되는 메서드. 클래스명과 동일해야 함. 일반적으로 클래스의 초기화를 담당. 생략될 경우 컴파일전 빈 생성자로 자동 추가.
  • 메서드 : 객체가 수행할 동작

6.6 필드 선언과 사용

class 클래스명 {
자료형 필드명;
자료형 필드명 = 초기값;
}

  • 필드는 인스턴스 생성시 초기값이 기술되어 있지 않으면 0에 준하는 값으로 초기화
class Car {

	String model = "그랜저";
	int speed;
	boolean start;

	Tire tire = new Tire();

}
Car c1 = new Car();
System.out.println(c1.model); //그랜저
c1.speed = 100;

6.7 생성자 선언과 호출

  • new 연산자는 클래스의 생성자를 호출
  • 생성자는 클래스의 인스턴스 생성시 가장 먼저 실행되는 메서드
  • 일반적으로 초기화를 담당
  • 생성자명은 클래스명과 동일

6.7.1 기본(default) 생성자

  • 모든 클래스는 생성자를 1개 이상 가져야 한다.
  • 클래스 정의시 생성자를 생략하면 컴파일러는 기본 생성자를 추가하여 컴파일

6.7.2 생성자 정의

class Car {
		String model;
		int maxSpeed;
		boolean start;
		Tire tire = new Tire();
}
  • this : 생성된 객체 자신

6.7.3 생성자 오버로딩

  • 오버로딩(overloading) : 매서드명은 동일하고 매개변수의 타입 및 수량을 달리하여 여러개를 정의
  • 생성자 오버로딩 : 생성자를 다양하게 정의

생성자 오버로딩

package sec02;

public class Car {
	String company = "현대자동차";
	String model;
	String color;
	int maxSpeed;
	
	Car() {}
	
	Car(String model) {
		this.model = model;
	}
	
	Car(String model, String color) {
		this.model = model;
		this.color = color;
	}

	Car(String model, String color, int maxSpeed) {
		this.model = model;
		this.color = color;
		this.maxSpeed = maxSpeed;
	}
	
	
}

// 다른 클래스, 오버라이딩(재정의)랑 다른거임 생성자를 여러개만드는 생성자 오버로딩 : 매개변수의 타입, 개수, 순서가 다르게 여러 개의 생성자 선언 

package sec02;

public class CarExample {

	public static void main(String[] args) {
		Car car1 = new Car();
		System.out.println("car1.company : " + car1.company);
		System.out.println();
		
		Car car2 = new Car("자가용");
		System.out.println("car2.company : " + car2.company);
		System.out.println("car2.model : " + car2.model);
		System.out.println();
		
		Car car3 = new Car("자가용", "빨강");
		System.out.println("car3.company : " + car3.company);
		System.out.println("car3.model : " + car3.model);
		System.out.println("car3.color : " + car3.color);
		System.out.println();
		
		Car car4 = new Car("택시", "검정", 200);
		System.out.println("car4.company : " + car4.company);
		System.out.println("car4.model : " + car4.model);
		System.out.println("car4.color : " + car4.color);
		System.out.println("car4.maxSpeed : " + car4.maxSpeed);
	}

}

6.7.4 다른 생성자 호출

  • 생성자 오버로딩에서 중복코드가 많을 경우(단계적으로 내용이 증가되는 형태일 경우) 공통 코드를 가진 생성자만 정의하고 나머지는 this()를 사용하여 공통코드 생성자를 호출

생성자 예제

package Example;

public class MemberService {
	
	boolean login(String id, String password) {
		if(id.equals("hong") && password.equals("12345")) {
			return true;
		}
		else {
			return false;
		}
	}
		
	void logout(String id) {
		System.out.println(id + "님이 로그아웃 되었습니다.");
	}
	
}

// 다른 클래스

package Example;

public class MemberServiceExample {

	public static void main(String[] args) {
		MemberService memberService = new MemberService();
		
		boolean result = memberService.login("hong", "12345");
		if(result) {
			System.out.println("로그인 되었습니다.");
			memberService.logout("hong");
		} 
		else {
			System.out.println("id 또는 password가 올바르지 않습니다.");
		}
		
	}
}

// 결과 hong과 12345가 일치하니, 로그인 되었습니다. hong님이 로그아웃 되었습니다.

6.8 매서드의 생성과 호출

6.8.1 매서드 정의

반환형 매서드명(매개변수, 매개변수, ...){ 메서드 실행문; ... }

  • 반환형(리턴 타입, Return Type)
  • 매서드의 실행결과를 호출한 장소로 반환할 경우의 자료형
  • 리턴값(retrun 문에서 기술된 값 또는 변수 또는 식의 결과)의 자료형과 일치해야 한다.
  • 만약 리턴값이 없을 경우 반환형을 void로 기술한다.
  • 매서드명 : 관례로 소문자로 시작
  • 매개변수 : 매서드 실행시 필요한 외부에서 전달되어지는 인수값을 저장할 변수
  • 매개변수는 지역변수로 취급한다.(메서드 종료시 메모리에서 삭제. 자동 변수)

int divide(int x, int y){...} //매개변수마다 형선언을 해야 함 int divide(int x, y){...} //이건 안됨

6.8.2 메서드 호출

  • 객체 내부에서 호출 : 메서드명(인수, 인수,...);
  • 객체 외부에서 호출 : 변수명.메서드명(인수, 인수,...);

매서드 선언과 호출

package sec02;

public class Calculator {
	void powerOn() {
		System.out.println("전원을 켭니다.");
	}
	
	void powerOff() {
		System.out.println("전원을 끕니다.");
	}
	
	int plus(int x, int y) {
		int result = x + y;
		return result; 
	}
	
	double divide(int x, int y) {
		double result = (double)x / (double)y;
		return result; 
	}

}

// 다른 클래스

package sec02;

public class CalculatorExample {

	public static void main(String[] args) {
		Calculator myCalc = new Calculator();
		
		myCalc.powerOn();
		
		int resultl = myCalc.plus(5, 6);
		System.out.println("result1 : " + resultl);
		
		int x = 10;
		int y = 4;
		
		double result2 = myCalc.divide(x, y);
		System.out.println("result2 : " + result2);
		
		myCalc.powerOff();
	}

}

6.8.3 가변길이 매개변수(배열형 매개변수)

반환형 메서드명(자료형... 변수명) { }

  • 매개변수는 입력된 값들의 길이만큼의 해당하는 배열로 생성하여 처리
package sec02;

public class Computer {
	
	int sum(int ... values) { // int[] values 이런 형식으로 만들면 res1, res2는 안된다. res3, res4는 가능
		int sum = 0;
		
		for(int i=0; i<values.length; i++) {
			sum += values[i];
		}
		
		return sum;
	}
	
}

// 다른 클래스

package sec02;

public class ComputerExample {

	public static void main(String[] args) {
		Computer myCom = new Computer();
		
		int res1 = myCom.sum(1,2,3);
		System.out.println("res1 : " + res1);
		
		int res2 = myCom.sum(1,2,3,4,5); // 길이가 달라져도 상관없고
		System.out.println("res2 : " + res2);
		
		int[] values = {1,2,3,4,5};
		int res3 = myCom.sum(values); // 배열도 가능하다
		System.out.println("res3 : " + res3);

		int res4 = myCom.sum(new int[] {1,2,3,4,5}); // 이런 배열 형식도 가능
		System.out.println("res4 : " + res4);

	}

}

6.8.4 return 문

  • 매서드를 종료하고 호출한 장소로 되돌아감
  • 호출한 장소도 되돌아갈 때 1개값을 포함하여 호출한 장소로 전달 형식 return; return 값_또는_변수_또는_식;
  • 주의 : 리턴값은 매서드의 리턴타입과 동일한 타입(자동 형변환 허용)이어야 한다.

6.8.5 매서드 오버로딩

  • 메서드명은 동일하되 매개변수의 타입, 수량, 순서를 달리하여 여러개를 정의한 것
  • 같은기능을 하되 매개변수의 종류가 다를 경우 매서드명을 달리하면 가독성 측면에서 불편, 네이밍 차원에서도 불편. 주의 : 반환형, 매개변수 이름은 오버로딩과 관련 없다. int add(int x, int y) {...} double add(int x, int y) {...} //오버로딩 아님. 메서드 중복 에러 int add(int num1, int num2) {...} //오버로딩 아님. 메서드 중복 에러

6.9 인스턴스 맴버

  • 인스턴스 : new 연산자를 통해 힙 영역에 생성된 객체
  • 맴버 : 클래스 내부에 선언된 요소(속성, 매서드)
  • 인스턴스 맴버 : 객체에 소속된 맴버(객체를 생성해야 사용할 수 있는 맴버). 힙 영역에 존재하는 맴버
  • 정적(static) 맴버 : 클래스에 고정된 맴버(객체 생성 없이도 사용가능한 맴버). 매서드 영역에 상주하는 맴버

6.9.1 this 키워드

  • 생성된 인스턴스 자신.
  • 인스턴스 내부에서 내부의 맴버를 호출할 때 사용.

6.10 정적 맴버

6.10.1 정적 맴버 선언 : static 키워드 사용

class 클래스명 { static 자료형 변수명; //정적 맴버 변수

        static 반환형 매서드명 (매개변수,...) {          //정적 맴버 매서드
                   메서드 내용;            
        }

}

6.10.2 정적 맴버 사용

Calculaotr myCal = new Calculaotr();
double result1 = 10 * 10 * myCal.pi;
int result2 = myCal.plus(10, 20);
int result2 = myCal.minus(100, 50);

6.10.3 정적 블록

  • 정적 맴버를 초기화 하기 위한 블록
  • 클래스가 메모리(메서드 영역)에 로드될 때 자동으로 실행

6.10.4 인스턴스 맴버 사용 불가

  • 맴버의 접근은 객체 생성전(staic 맴버)과 생성 후(인스턴스 맴버)로 나눈다.
  • 인스턴스 맴버는 객체 생성전 static을 통해 사용할 수 없다.
public class Exam18 {
	
			int iv = 10;
			static int cv = 20;
	
			int iv2 = cv;
//	  static int cv2 = iv; // 라인 A 정적 변수 초기화에 인스턴스 변수 사용 불가

		static void staticMethod1() {
			System.out.println(cv);
//		System.out.println(iv); // 라인 B 정적메서드에서 인스턴스 변수 사용 불가
		}

		void instanceMethod1() { 
			System.out.println(cv); 
			System.out.println(iv);  //라인 C 
		} 

		static void staticMethod2() { 
			staticMethod1(); 
//		instanceMethod1();  //라인 D static 메서드에서는 인스턴스 메서드를 사용할 수 없다.
		} 

		void instanceMethod2() { 
			staticMethod1();  //라인 E 
			instanceMethod1(); 
		} 

}

6.11 Getter와 Setter(메서드)

  • 전제 조건 : 외부에서 필드를 마음대로 접근하면 필드 값에대한 무결성이 깨질수 있다. 이를 보완하기 위해 필드를 private으로 노출을 막고 메서드를 public으로 하여 노출시킨다음 메스들 통해 필드값을 변경하게 한다.
  • Setter : 필드의 값을 설정하는 메서드
  • Getter : 필드의 값을 가져오는 메서드
  • return 타입이 boolean인 경우 is접두사를 사용함.

Getter, Setter

package sec08;

public class Car {
	private int speed;
	private boolean stop;
	
	public int getSpeed() {
		return speed;
	}
	
	public void setSpeed(int speed) {
		if(speed < 0) {
			this.speed = 0;
		}
		else {
			this.speed = speed;			
		}
	}
	
	public boolean isStop() { // boolean 타입인 경우 get이 아니라 is로 나온다.
		return stop;
	}
	
	public void setStop(boolean stop) {
		this.stop = stop;
		if(stop == true) {
			this.speed = 0;
		}
	}

}

// 다른 클래스

package sec08;

public class CarExample {

	public static void main(String[] args) {
		Car myCar = new Car();
		
		myCar.setSpeed(-50);
		System.out.println("현재 속도 : " + myCar.getSpeed()); // 0
		
		myCar.setSpeed(60);
		System.out.println("현재 속도 : " + myCar.getSpeed()); // 60
		
		if(!myCar.isStop()) {
			myCar.setStop(true);
		}
		System.out.println("현재 속도 : " + myCar.getSpeed()); // 0
	}

}

// 패턴 : 객체지향 프로그래밍의 디자인(설계) 방식
// 싱글톤 패턴 : 객체가 1개만 생성되도록 디자인된 패턴 (여러개의 인스턴스에 의해 메모리가 낭비되는걸 방지하기 위해서) --> 생성자를 private으로 선언하여 외부에서 무분별하게 생성못하도록 막음.
//               public static으로 선언된 메서드를 통해 1개의 인스턴스만 생성되도록 제한.

6.12 싱글톤 패턴

  • 패턴 : 객체지향 프로그래밍의 디자인(설계) 방식
  • 싱글톤 패턴 : 객체(인스턴스)가 1개만 생성되도록 디자인된 패턴
  • 생성자를 private로 선언하여 외부에서 무분별하게 생성하지 못하도록 막음
  • publuc static으로 선언된 메서드를 통해 1개의 인스턴스만 생성되로록 제한
package sec09;

public class Singleton {
	private static Singleton singleton = new Singleton();
	private int value;
	
	private Singleton() {
		
	}
	
	static Singleton getInstance() {
		return singleton;
	}
	
	public int getValue() {
		return value;
	}
	
	public void setValue(int value) {
		this.value = value;
	}
	
}

// 다른 클래스

package sec09;

public class SingletonExample {

	public static void main(String[] args) {
//		Singleton obj1 = new Singleton(); Err, private 이기 때문에
//		Singleton obj2 = new Singleton();
		
		Singleton obj1 = Singleton.getInstance(); 
		Singleton obj2 = Singleton.getInstance();
		
		if(obj1 == obj2) {
			System.out.println("같은 Singleton 객체 입니다.");
		}
		else {
			System.out.println("다른 Singleton 객체 입니다.");
		}
		
		System.out.println("obj1.value : " + obj1.getValue()); // 0
		System.out.println("obj2.value : " + obj2.getValue()); // 0
		
		obj1.setValue(10);
		System.out.println("obj1.value : " + obj1.getValue()); // 10
		System.out.println("obj2.value : " + obj2.getValue()); // 10
		
		obj2.setValue(50); 
		System.out.println("obj1.value : " + obj1.getValue()); // 50 즉, obj1과 obj2는 연결되어 있다.
		System.out.println("obj2.value : " + obj2.getValue()); // 50
	}

}