Programming/Java

[Java9 프로그래밍] 08. 객체지향 모델링

빠모스 2020. 3. 13. 20:37
반응형

객체지향이란?

  • 데이터 타입을 별도로 만들어 데이터를 처리한다.
  • 객체(Object)로 프로그램을 작성
  • 전체 어플리케이션을 객체로 분리하여 보델링

ex) 학생 관리타입을 만들고자 한다.

학생의 학번, 이름, 주소, 현재 학년 등에 대한 정보를 가지고 있는게 ‘학생’이다.

학생에 대한 이러한 정보를 하나의 타입에 넣어서 캡슐화시켜서 만든것이 타입, 객체다.

홍길동이라는 학생은 이름이 홍길동, 나이가 20, 성별 남자, 주소는 서울이다. 이 네가지 정보를 가지고 있는 것이 홍길동이라는 객체다. 

이 학생 개개인의 객체를 만들기 위해서는 이름, 나이, 성별, 주소 데이터를 가지고 있어야 함. 

모든 객체들이 똑같은 타입, 똑같은 구조로 만들어지는 것을 지원하는게 “클래스”이다.

자바는 클래스와 객체 모두를 사용한다.

즉, 자바는 객체를 만들기 위해선 꼭 클래스를 만들어야 한다. 이렇게 데이터 타입을 만들고 실제 object를 만들어야 한다. 클래스에서 object가 파생되는 것. 클래스를 기반으로 객체를 만든다.

 

어떤 언어는 클래스 필요 없이 바로 객체를 만들 수 있는데, 대표적인것이 javascript다. 스키마 없이 바로 객체 생성 가능.

 

 

객체 내부에 들어있는 것은?

 

  • 데이터와 함수.
  • 함수는 객체 내부의 데이터와 연관된 작업을 하며 객체 내부의 데이터를 변형시키거나 외부에서 객체 내부의 데이터를 접근할 수 있게 해주는 함수다. 
  • 객체가 발명되기 전 함수를 호출하는 방식으로 프로그램 작성
  • 함수는 작업을 공유할 수 있게 해줌
  • 함수에 한 차원 더해서 객체 자체의 상태를 포함함 (상태 = 객체 내부 데이터)
  • 객체의 메소드를 호출할 때 내부 상태가 어떻게 바뀌는지 알 필요가 없음
  • 캡슐화, encapsulation

 

객체 사용 방법 및 사례

 

객체는 바로 사용할 수 없고, 클래스를 통해 객체를 생성 후 사용

 

<예시 1>

자바의 내장 클래스 Scanner을 사용할 수 있게, reader라는 객체를 생성하는 코드

import java.util.*;

public class GettingObjectOriented {
	public static void main(String[] args) {
		Scanner reader = new Scanner(system.in);
		System.out.println(reader.next());
	}
}

=> Scanner 클래스 타입의 객체 reader를 생성한다. new라는 키워드가 직접적으로 객체를 만들겠다는 키워드다. system.in 파라미터는 생성자와 관련된 파라미터다.

reader 객체 내부의 next() 함수를 호출한다. 이 함수는 reader객체 내의 데이터를 실제로 바꾼다.

 

 

객체 참조

 

  • 변수에는 오직 객체의 참조만을 담을 수 있음
  • 두 참조가 같은 객체를 가리킬 수도 있음

<예시 2>

자바 내장클래스 LocalDate의 객체 date를 of 메소드를 통해 만드는 코드

LocalDate date = LocalDate.of(2016, 1, 1);

=> LocalDate는 java8에서 새로 생긴, 날짜를 관리하는 클래스다.

date라는 이름의 객체를 만들고, LocalDate의 of 메소드를 통해 만들 수 있다. 일반적으로 new를 통해 만들 수 있지만, of를 통해 객체를 만들때는 ‘팩토리 메소드’라고 한다. 

 

=> date라는 Stack 변수에는 주소값이 들어가게 되고, 실제 값은 Heap에 12.03.2020이라는 실제 값이 저장됨.

 

<예시 3>

ArrayList 패키지의 List 클래스 객체 friends와 people을 new 메소드를 통해 만드는 코드

List<String> friends = new ArrayList<>();
List<String> people = new ArrayList<>();

=> friends와 people엔 주소값이, heap 메모리 영역에 실제 값 Peter과 Paul이 저장됨.

 

<예시 4>

date = null;

=> date에 null이라는 값이 들어가면서 date는 아무런 객체도 참조하지 않게 된다. 더이상 객체가 참조되지 않는다. 이걸 무시하고 date 변수를 사용하게 되면 null point exception이라는 에러가 발생하게 된다.

 

 

사용자 정의 클래스 만들기

 

클래스 작성

  • 클래스명과 파일명 동일이 원칙 - Vehicle.java
  • Naming convention
     

Vehicle이라는 클래스에 필요한 데이터는 문짝의 개수(doors), 속도(speed), 색상(color)이다.

run()이라는 메소드는 자동차를 실제로 운행시키는 메소드다. run()을 작동시키면 speed 데이터가 달라지리라 예상된다. 클래스 이름은 대문자, 변수와 메소드는 소문자로 시작한다.

 

 

사용자 정의 클래스 - 멤버 변수, Member variable

 

  • 객체는 데이터 + 함수로 구성
  • 데이터에 해당되는 부분이 멤버변수
  • 필드, field
  • 인스턴스 변수, instance variable

<예시 1>

Person이라는 클래스를 정의한다. firstName, lastName, birthday라는 멤버변수(=필드, 인스턴스 변수)를 만들어 fullName() 메소드를 통해 firstName과 lastName을 결합한 fullName을 반환한다.

public class Person {
	public String firstName; //=> 멤버변수, 필드, 인스턴스 변수
	public String lastName;
	public LocalDate birthday;
	public String fullName() { //=> 메소드, 인스턴스 메소드
		return firstName + “ “ + lastName;
	}
}

 

메소드

 

 

  • 접근 제한자 : Java는 메소드 혹은 변수마다 접근의 범위를 제한시키기 위해 접근 제한자를 지원 
  • Private 접근 제한자를 쓰는 이유 : 내부에서만 사용하기 위해. public 메소드가 너무 길어지게 되면 메소드를 분리시킨다. 100라인정도만 넘어가도 메소드가 커진다고 봄. 메소드는 작게 관리하는것이 나중에 확장성에서 유리하게 된다. 이렇게 쪼갤때 Private을 많이 사용한다.
  • Protected 접근 제한자 : 하위 클래스에서만 접근할 수 있다는 뜻. 

<예시 2>

개의 몸무게 클래스 Dog에서 setWeight와 getWeight의 getter, setter 메소드를 만들고 메인 함수에서 Dog 클래스 내의 데이터와 함수를 쓰기 위해 객체 d를 만든다. 객체.setWeight을 통해 42라는 몸무게를 전달하고, 객체.getWeight을 통해 반환된 몸무게값을 프린트한다.

public class TestDog {
	public static void main( String[] args ) {
    	Dog d = new Dog(); //Dog 객체 생성
        d.setWeight(42); // setWeight() 호출하며 42 전달
        System.out.println( "Dog d's weight is" + d.getWeight() );
        					// getWeight() 통해서 weight 받기
        }
}
public class Dog {
	private int weight;
    public void setWeight(int newWeight) {
    	weight = newWeight; // 위에서 파라미터를 통해 42를 전달하고 42를 멤버변수인 weight에 할당
    }
    
    public int getWeight() {
    	return weight; // 호출한 쪽으로 weight 리턴
    }
}

=> 자바에서는 클래스 내부 변수를 private로 하고, public 메소드로 이 변수를 바꿔주는 쪽으로 한다. 자바의 문화는 field는 private으로 묶고, set, get 메서드를 통해 변수에 접근한다.

 

 

접근자 메소드와 변경자 메소드

 

  • 객체의 상태를 바꾸는 메소드 - 변경자 : setter, mutator라고도 함
  • 객체의 상태를 알려주는 메소드 - 접근자 : getter
  • 사실 변경자를 제외한 대부분의 메소드는 접근자라고 할수 있음
  • getter, accessor라고도 함
  • 객체 변경은 위험할 수 있어 가능한 접근자 메소드만 제공하는 방법 고려
  • 두 연산이 한 객체를 동시에 변경할 때 - 멀티 CPU가 보편화

 

생성자, Constructor

객체 생성

  • 클래스의 생성자를 통해서 객체를 생성할 수 있음
  • 주로 멤버변수를 초기화하는데 사용

 

특징

  • 클래스 이름과 같다.
  • return 타입이 없다.
  • 상속되지 않는다.
  • 객체 생성시 new 키워드를 만났을 때 사용된다.
  • public으로 선언된다. 그러나 private으로 선언도 가능하다. 
public class Dog {
	private int weight;
    public Dog() {
    	weight = 42;
    }
}

 

생성자 생성 

 

public class Calculator {
	private int a;
    private int b;
    
    public Calculator ( ) {
    	a = 10;
        b = 50;
    }
    
    public int f (int x) {
    	return a * b + x;
    }
}

 

=> public Calculator ()가 생성자.

 

 

다른 생성자에서 특정 생성자 호출하기

생성자 오버로딩 

public class Calculator {
	private int a;
    private int b;
    
    public Calculator ( ) {
    	a = 10;
        b = 50;
    }
    
    public Calculator ( int a, int b ) {
    	this.a = a;
        this.b = b;
    }
    
    public int f (int x) {
    	return a * b + x;
    }
}

 

=> this 키워드 : 외부에서 들어오는 파라미터 a, b를 나의 멤버변수로 세팅하겠다는 의미로 this를 활용. 내 자기 자신에 있는 데이터, 멤버변수를 의미한다.

 

 

기본 생성자, Default constructor

 

  • 인자 없는 생성자
  • 생성자를 명시적으로 만들지 않으면 자동으로 생김
  • 인자 있는 다른 생성자를 작성하면 기본 생성자는 생기지 않음

=> 생성자를 안만들면 new 를 이용한 기본 생성자가 만들어지지만, public Calculator ( ) 이런 식으로 명시적으로라도 만들어주면 기본 생성자는 생기지 않는다.

 

ThinkPoint

모듈러 프로그래밍이란?

프로그램을 부품처럼 설계하는 방법. 프로그램을 모듈화하여 독립성을 갖도록 함으로써 다른 모듈에 영향을 받는 일이 없이 일부 모듈의 개량이나 재번역이 가능하다.

 

반응형