[Day06] java-basic : 객체지향과 클래스

4 분 소요

객체지향이란?

  • 눈에 보이는 사물들을 프로그래밍화 시키고 싶은 것이 객체 지향이다.
  • 물론 눈에 보이지 않는 사물들을 객체화 하여 프로그래밍화 하기도 한다.

  • 절차지향은 행동에 기반한 프로그래밍법이다.
  • 절차지향은 문장단위로 만들어진다.
  • 문장 중심의 절자지향 프로그램보다는 주어와 동사 기반의 객체지향 프로그램이 유지보수에 능하다.
  • 눈에 보이는 사물 하나를 단위로 만들어주는 것을 객체 지향 프로그램이라고 한다
  • 객체지향은 절차지향보다 사물의 주체가 중요해진 것이다.
  • 고양이가 운다, 고양이가 먹는다 (X) -> 고양이 (O)

  • 객체 지향 프로그램에서는 사물끼리 통신하고 대화하도록 만들어주는 것이 중요하다.
  • nextInt()라는 메소드의 주체가 ScannerRandom이냐에 따라 결과가 달라지는 것이 바로 객체지향이다.

  • 추상화 : 실제 눈에 보이는 사물들 중에서 내가 필요로 하는 기능만 뽑아서 프로그램에서 똑같은 사물을 구현해내는 것을 추상화시킨다고 한다.

  • 객체지향에서 디자인 패턴은 꼭 봐야 하는 책이다.

클래스란?

  • 객체지향에서 필요한 사물을 추상화시켜서 만든 단위가 클래스이다.
  • 하나의 사물은 명사와 동사로 이루어져 있다.
  • 사물의 특징(속성)을 명사형태, 행동(동작)을 동사라고 보통 얘기한다.
  • 클래스에서 사물의 추상화된 특징을 변수로 구성하고, 사물의 추상화된 행동들을 메소드로 구성하게 된다.
  • 클래스를 객체의 생선처, 객체를 생성하는 틀이라고 하는 이유 : 고양이라는 객체를 바로 만드는게 아니고, 애완동물의 특징을 구현한 클래스를 활용해서 고양이(객체)를 만들어낼 수 있기 때문이다.
  • 클래스 자체가 객체가 아니고 클래스는 객체를 만들 수 있는 설계 도면이다.
  • 객체를 만들기 위해서는 heap 영역에 메모리를 할당해야 한다.

  • JVM이 인식하는 단위가 클래스이다.
  • JVM은 java.lang만 JVM에 올린다.
  • 혹은 import한 것과 main메소드만 올린다.?

객체의 구성

  1. 멤버변수 = 속성
  2. 메소드 = 동작
  • 필요한 객체를 프로그램이 인식하게 하기 위해서는 1) 클래스 설계 => 2) 클래스로 객체 생성(new) => 3) 생성된 객체를 클래스에 정의된 속성과 동작을 가지고 동작

  • heap 영역에 있는 모든 요소를 객체라고 하지만, new를 통해 heap 영역에 객체를 만들면 이렇게 만들어진 객체를 인스턴스 객체라고 한다.
  • 예를 들어 TV tv = new TV() 에서 tv는 참조변수, new TV()에서 TV()가 인스턴스 객체가 되는 것이다.
  • 이때 인스턴스 객체를 제어하기 위해서는 참조변수 tv를 통해 제어한다.

클래스의 선언

[접근제한자][활용제한자(final/abstract)] class 클래스명 {
  속성 정의 (멤버변수)
  기능 정의 (메소드)
  
}
  • 하나의 클래스명.java파일에는 하나의 클래스만 존재한다?

code실습

  • 때에 따라서는 Car클래스를 CarMain 안에 설계할 때도 있는데 일반적으로는 따로따로 설계하는 것이 좋다.

Car.java

  • Car.java는 참조클래스이다.
  • 참조 클래스 : main메소드 없이 사물에 대한 추상화만 시킨 클래스이다.
  • 메인메소드는 프로그램이 시작되었어~ 끝났어~하고 알려주는 용도이기 때문에 모든 java파일마다 main메소드를 가질 필요는 없다.
// 참조 클래스
public class Car {

	String 	name;
	int 	price;
	String 	company;
	
}

CarMain.java

  • CarMain.java는 실행클래스이다.
  • 눈에 보이는 사물을 추상화 시킨 클래스는 아니다.
  • 다만 main메소드를 통해 Car를 실행시키기 때문에 실행클래스 또는 동작 클래스라고 한다.
// 실행 클래스
public class CarMain {
	public static void main(String[] args) {
		
		Car c = new Car();
		
		// c차의 이름 출력하기
		System.out.println(c.name);
		
		// c차의 특성 지정하기
		c.name = "소나타";
		c.price = 3200;
		c.company = "현대";
		
		// c2차의 인스턴스 객체 만들고 특성 지정하기
		Car c2 = new Car();
		c2.name = "K5";
		c2.price = 3000;
		c2.company = "기아";
		
	}
}
  • Ram이라는 메모리에 자동차를 만들어야 한다.
  • 자바에서는 눈에 보이는 사물을 만드는 키워드가 new이다.
  • new Car();를 하면 heap 영역에 자동차라는 객체를 만들게 된다.

  • new키워드로 만들어진 객체는 자동 초기화된다. (int는 0으로, String은 null로 초기화됨)

  • c의 객체에 속해있는 name에 접근하기 위해서는 c.name으로 접근한다.
  • 단축키 : c.name을 드래그 하고 ctrl + space하면 System.out.println(c.name); 자동완성 가능하다.
  • name은 데이터형이 String이기 때문에 별도의 “소나타”의 공간이 만들어지고 c.name이 “소나타”의 주소???을 가르킨다.
// 실행 클래스
public class CarMain {
	public static void main(String[] args) {
		
		Car c = new Car();
		
		// c차의 이름 출력하기
		System.out.println(c.name);
		
		// c차의 특성 지정하기
		c.name = "소나타";
		c.price = 3200;
		c.company = "현대";
		
		// c2차의 인스턴스 객체 만들고 특성 지정하기
		Car c2 = new Car();
		c2.name = "K5";
		c2.price = 3000;
		c2.company = "기아";
		
		
		// shallow copy
		c = c2;
		
		// c, c2의 정보 출력하기
		System.out.println("모델명 : " + c.name 
						+ ", 가격 : " + c.price
						+ ", 제조사 : " + c.company);

		System.out.println("모델명 : " + c2.name 
				+ ", 가격 : " + c2.price
				+ ", 제조사 : " + c2.company);
	}
}
  • c = c2;라면 c라는 참조변수가 가진 값이 heap 영역에 존재하는 c2의 주소로 바뀌게 된다.
  • heap 영역에 존재하던 c의 객체는 가리키는 참조변수가 없기 때문에 쓸모가 없는 메모리 손실이 발생한다.
  • 이때 이런 쓰레기 값을 자동으로 처리하는 자바만의 특성이 가비지컬렉터이다.

Handphone.java

  • 핸드폰 사물의 특성을 정의한 참조클래스

HandphoneMain.java

  • 핸드폰 실행 클래스
  • 인스턴스 객체를 만든 뒤, 만들어진 객체를 요소로 하는 배열을 만든다.
public class HandphoneMain {

	public static void main(String[] args) {
		// "홍길동", "010-2222-2222", "삼성"을 가지는 Handphone 인스턴스 객체 만들기
		Handphone hp = new Handphone();
		
		hp.name = "홍길동";
		hp.phone = "010-2222-2222";
		hp.company = "삼성";
		
		// "윤길동", "010-1111-1111", "애플"을 가지는 객체 hp2 생성
		Handphone hp2 = new Handphone();
		
		hp2.name = "윤길동";
		hp2.phone = "010-1111-1111";
		hp2.company = "애플";

		// Handphone 데이터형인 배열을 만들어보기=================================================================================
		Handphone[] hpArr = {hp, hp2};
		
		// index를 활용한 방법
		for(int i = 0; i < hpArr.length; i++) {
			System.out.println("소유주명 : " + hpArr[i].name);
			System.out.println("핸드폰번호 : " + hpArr[i].phone);
			System.out.println("핸드폰제조사 : " + hpArr[i].company);
		}
		
		// 1.5버전 foreach문 활용한 방법
		for(Handphone h : hpArr) {
			System.out.println("소유주명 : " + h.name);
			System.out.println("핸드폰번호 : " + h.phone);
			System.out.println("핸드폰제조사 : " + h.company);
		}
		
	}

}

image

HandphoneMain02.java

  • 배열을 먼저 생성하는 방법

public class HandphoneMain02 {
	public static void main(String[] args) {
		
		Handphone[] hpArr =  new Handphone[3];
		
		/* 	메모리에 어떻게 그려질까??
		 	Handphone형의 참조변수만 만들 뿐, Handphone형의 인스턴스는 만들어지지 않는다!
		*/
		
		for(int i = 0; i < hpArr.length; i++) {
			System.out.println(hpArr[i]); // null값이 출력됨
			/* hpArr[i] 는 null이므로, hpArr[i].name은 nullPointerException이 발생한다. */
			
			// 핸드폰 인스턴스 객체 만들기
			hpArr[i] = new Handphone();
			System.out.println(hpArr[i]); //  객체를 생성했기 때문에 주소값이 출력됨
		}
		
	}

}

image

  • 배열 선언과 인스턴스화를 동시에 하는 경우
public class HandphoneMain02 {
	public static void main(String[] args) {
		
		// 다른 방법
		Handphone[] hpArr2 = new Handphone[] {new Handphone(), new Handphone(), new Handphone()};
				
		hpArr2[0].name = "홍길동";
		hpArr2[0].phone = "010-1111-1111";
		hpArr2[0].company = "삼성";
		
		hpArr2[1].name = "윤길";
		hpArr2[1].phone = "010-2222-1111";
		hpArr2[1].company = "애플";
		
		hpArr2[2].name = "삼실";
		hpArr2[2].phone = "010-2222-1111";
		hpArr2[2].company = "화웨이";
		
		for(Handphone hp : hpArr2) {
			System.out.println(hp);
			System.out.println("소유주명 : " + hp.name);
			System.out.println("번호 : " + hp.phone);
			System.out.println("회사 : " + hp.company);
		}
		
	}

}

image