Leeyebin의 블로그

[JAVA] 객체지향 본문

프로그래밍/JAVA

[JAVA] 객체지향

안되면될때까지 2017. 6. 5. 14:43

객체지향 프로그래밍(OOP : Object-Oriented Programming)

  • 객체 지향 프로그래밍은 컴퓨터 프로그래밍의 패러다임의 하나이다.
  • 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, '객체'들의 모임으로 파악하고자 하는 것이다.
  • 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.


객체란?

  • 실세계와 비교하자면 세상에 존재하는 모든 사물이 객체
  • 저장 공간에 할당된 공간(객체 참조 변수를 통해 해당 공간에 접근)
  • 하나의 클래스를 통해 다수의 객체가 생성되지만 각각의 객체는 공유함
  • 속성 + 행위


클래스란?

  • 같은 속성들과 기능들을 가진 객체들을 총칭하는 개념
    • (이 개념적인 클래스를 통해 실체화 된 것이 객체(인스턴스))
  • 객체는 필드와 메소드를 가진다.
    • (클래스를 통해 실체화된 객체는 필드를 통해 고유한 속성을 가지고 메소드로 행위를 한다.
    • 클래스 객체참조변수명 = new 클래스(); //new 연산자를 통해 객체가 메모리에 할당되고 해당 객체의 생성자가 호출된다.

클래스 구성 멤버
public class 자동차 {
	String 이름; //필드
	
	public 자동차(){ //생성자
	}
	
	public void 시동켜기(){ //메소드
		
	}
}

필드(Field)

  • 라이프 사이클
    • 필드는 객체 소멸 시 함께 소멸
    • 변수는 생성자 또는 메서드 수행이 종료되면 소멸
  • 초기화
    • 필드 선언 시
      • 필드의 초기 값이 모든 객체에 대해 동일한 경우
    • 생성자에서
      • 객체 생성 시점이 외부의 값으로 대입이 필요한 경우


생성자
  • new 연산자로 호출되며, 객체 생성 시 초기화를 담당.
    • 클래스 이름으로 되어 있고 리턴타입이 없다.
  • 명시하지 않으면 JVM이 기본 생성자 생성(인자가 있는 생성자를 만들면 생성자가 있다고 JVM이 판단해서 기본생성자를 따로 만들지 않아준다.)
  • 상속 관계에서 객체 생성은 상위클래스가 먼저 초기화 되고, 하위 클래스가 초기화 된다.


메소드(Method)

  • 객체의 동작에 해당하며 해당 객체의 필드를 읽고 수정하는 역할과 객체간의 상호작용 역할
  • 외부로부터 값을 받을 수도 있고 실행 후 외부로 값을 반환 할 수도 있다.
  • 선언부와 실행 블록으로 구성
    • 선언부를 시그니처라고도 한다.(반환타입, 메소드명, 매개변수)


객체 vs 클래스

  • 클래스는 메소드 영역에 생성
  • 객체는 힙 영역에 생성
  • 객체의 메소드가 수행되면 스택 프레임이 생성
  • 메소드 내의 지역변수들은 스택프레임의 스택에 쌓임

JVM관련 참고하면 좋은 블로그

추후에 추가할 것



객체간의 관계

사람 ---사용관계--->자동차---상속관계--->기계

자동차<---집합 관계---엔진,타이어,핸들


  • 집합관계
    • 하나는 완성품, 하나는 부품
  • 사용 관계
    • 객체 간의 상호 작용
    • 하나의 객체가 다른 객체의 메소드를 호출하여 원하는 결과를 얻어냄
  • 상속 관계
    • 상위 객체를 기반으로 하위 객체를 생성하는 관계
    • 상위 객체는 종류/분류. 하위 객체는 구체적인 사물에 해당


객체지향의 4대 특성


*캡슐화(Encapsulation)

  • 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록 함(정보은닉)
  • 변화에 유연한 대응
  • 필드에 해당되는 건 최대한 감춰라.
  • 메소드만 접근하도록(너는 이것만 사용해)



Getter / Setter

  • 객체의 데이터를 외부에서 마음대로 읽고 변경할 경우 객체의 무결성이 깨어질 수 있기 때문에 외부에서 직접적으로 접근하는 것을 막는다.
  • 데이터는 외부에서 접근할 수 없도록 막고 메소드는 공개해서 외부에서 메소드를 통해 데이터에 접근하도록 유도
  • 필드 타입이 boolean일 경우 is로 시작하는 것이 관례


*상속(inheritance)

  • 상속의 목적은 재사용과 확장(자바에서의 상속에 해당하는 키워드는 extends)
  • 상위 객체를 재사용해서 하위 객체를 쉽고 빨리 설계할 수 있도록 도와준다.
  • 이미 잘 개발된 객체를 재사용해서 새로운 객체를 만들기 때문에 중복 코드를 줄여준다.
  • 상속에는 is a 관계가 성립한다. (고양이는 포유류다. 말은 포유류다. 등)
    • 하위클래스는 상위클래스이다.(LSP - 리스코프 치환 원칙 / SOLID의 L에 해당된다.) 
  • 상속에서의 메모리(하위 클래스를 생성하면 메모리에 상위클래스도 함께 적재된다.
  • 자바에서는 다중 상속을 지원하지 않는다.(다이아몬드 상속 문제) - 이 문제를 해결하기 위해 인터페이스를 제공한다.(추상메소드)


  • 인터페이스(interface)
    • 다중 상속 가능
    • 인터페이스의 메소드들은 전부 추상 메소드
    • 모든 메소드는 기본적으로 public 접근 제한
    • 하위 클래스에서는 implements 키워드를 사용하여 인터페이스를 구현
    • 이반 클래스처럼 new 키워드로 생성될 수 없음
    • 인터페이스들끼리의 상속 가능
    • 인터페이스도 결국에는 컴파일러를 통해 .class 파일로 생성되기 때문에 물리적인 형태는 클래스와 동일
    • 인터페이스는 무조건 구현해야한다.
  • 인터페이스 구성 요소
    • 상수 필드(Constant Field)
    • 추상 메소드(Abstract Method)
      • 인터페이스에 선언된 메소드는 모두 public abstract를 붙인 것과 같음.
    • 디폴트 메소드(Default Method)
      • 자바8
      • 기존 인터페이스를 확장해서 새로운 기능을 추가하기 위해서 사용
    • 정적 메소드(Static Method)
      • 자바8
      • 인터페이스만으로 호출 가능
  • 인터페이스의 default 메소드
    • java8에서 함수형 프로그래밍 요소들이 들어오면서 하위호환성을 위해 불가피하게 추가
    • interface에도 구현 메소드를 가짐으로써 다중 상속의 문제점이 다시 불거짐(다이아몬드 상속 문제)
    • 다중 상속 시 명확한 메소드 호출을 위해 상위 인터페이스의 메소드 명시
  • 익명 클래스(Anonymous Class)
    • 일회성의 구현 객체를 만들기 위해서 클래스를 새로 선언하는 것은 비효율적
    • 소스 파일을 만들지 않고도 구현 객체를 만들 수 있는 방법
    • 하나의 메소드를 가진 익명 클래스는 람다로 전환 가능
    • 익명 클래스 역시 물리적으로는 컴파일러에 의해 .class 파일로 생성된다.(Classfile1.class 와 같이 뒤에 증가되는 숫자 값으로 파일 생성)


*추상화(Abstraction)

  • 구체적인 것을 분해해서 관심 영역에 대한 특성만을 가지고 재조합 하는 것.
    • 관심영역 = 어플리케이션 경계 = 도메인 = 컨텍스트
  • 추상화 = 모델링 = 클래스 설계
    • 추상 클래스(Abstract Class)
    • 추상 메서드가 하나 이상 포함된 클래스
    • Class 앞에 abstract 키워드를 붙여서 표현
    • Abstract와 final 키워드는 함께 사용할 수 없다.
    • Abstract 메서드는 하위 클래스에서 반드시 구현해야 한다.
    • 일반 클래스처럼 new 키워드를 사용하여 생성할 수 없음.


추상클래스 vs 인터페이스

  • 추상 클래스는 extends, 인터페이스는 implements 키워드 사용
  • 추상 클래스는 필드를 가질 수 있지만 인터페이스는 불가능
    • 인터페이스에서 Static 변수는 가질 수 있음
  • 추상 클래스도 클래스이기 때문에 다중 상속이 불가능
  • 다중 상속이 불가능한 제약을 인터페이스로 해결
    • 인터페이스는 메서드의 구현부분과 필드가 없기 때문에 다중상속 가능
  • 추상 클래스는 클래스를 상속 받아서 기능을 이용하거나 확장하는 목적
  • 인터페이스는 메서드 구현을 강제하여 하위 클래스에게 같은 동작을 행하도록 함.

어떤 것을 사용할 것인가.

  • 추상 메서드만으로 가능한 경우에는 인터페이스를, 공통된 구현 부분이나 필드가 필요한 경우에는 추상클래스를 사용한다.
  • 애초에 클래스를 설계할 때 필드를 가질 수 없다는게 명확하면 인터페이스를 하는 것을 권장한다.


*다형성(Polymorphism)

  • 같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질
  • 하위 클래스는 상위 클래스나 인터페이스로 자동 타입 변한이 가능
  • 하위 클래스로 생성된 인스턴스는 하위클래스의 객체 참조변수에 대입되고 상위 클래스의 객체참조변수에 대입되나 같은 주소를 가리킨다.
    • sub == super(객체간 == 연산자는 주소 비교)
    • 상위 클래스로 변환된 경우 상위 클래스에 선언된 필드와 메서드에만 접근 가능
  • 강제 타입 변환(Casting)
    • 상위 클래스를 하위 클래스로 강제 변환
    • instanceof로 상속관계가 맞는지 확인
    • 확인 없이 다른 클래스로 캐스팅 하면 ClassCastException 발생

오버라이딩(Overrideing)
  • 상속된 메서드의 내용이 하위 클래스에 맞지 않을 경우, 하위 클래스에서 동일한 메서드를 재정의 하는 것.
  • 상위 클래스의 메서드는 숨겨지기 때문에 메서드 호출 시 하위 클래스의 메서드가 호출된다.
    • 상위 클래스의 메서드와 동일한 시그니처를 가야한다.
    • 접근 제한을 더 강하게 오버라이딩 할 수 없다.
    • 새로운 예외를 throws할 수 없다.

오버로딩(Overloading)

  • 클래스 내에 같은 이름의 메서드를 여러 개 선언하는 것.
  • 오버로딩 된 메서드를 호출할 경우 JVM은 매개값의 타입을 보고 메서드를 선택
    • 타입이 일치하지 않을 경우 타입 변환이 가능한지 검사


ETC


Call By


Call By Value : 값에 의한 전달

  • 기본 자료형은 저장하고 있는 값이 전달(복사) 된다.
  • 대입문 사용시 / 인자 전달 시 / 메서드 리턴 시


Call By Reference : 참조/주소에 의한 전달

  • 객체참조변수에 주소값을 대입하여 힙 영역에 존재하는 객체 참조
  • 포인터


static

  • 클래스에 고정된 멤버로서 객체를 생성하지 않고 사용할 수 있는 필드와 메서드
  • static 필드와 메서드는 클래스에 고정된 멤버이므로 클래스 로더가 클래스(바이트 코드)를 로딩해서 메서드 메모리영역에 적재할 때 클래스별로 관리된다.
    • 클래스 로딩이 끝나면 바로 사용 가능
  • static 요소들은 클래스 이름으로 접근하는 것이 좋다.
    • 인스턴스를 통해 접근할 경우 인스턴스를 먼저 훑고나서 없는 걸 확인한 후 클래스를 참조하기 때문에 하나의 스텝이 더 생긴다.
  • static 필드는 선언과 동시에 초기값을 주는 것이 보통이지만 초기화 과정이 복잡한 경우 static 블럭을 사용할 수 있다.
    • 클래스가 메모리로 로딩 될 때 자동으로 수행된다.
    • 인스턴스가 없어도 실행되기 때문에 인스턴스 필드나 메서드, this 키워드를 사용할 수 없다.

인스턴스 vs static
인스턴스 필드 vs static필드
  • 객체마다 가지고 있어야 할 데이터라면 인스턴스 필드로 선언
  • 객체마다 가지고 있을 필요성이 없는 공용적인 데이터라면 static 필드로 선언
인스턴스 메서드 vs static 메서드
  • 인스턴스 필드를 이용해서 실행해야 한다면 인스턴스 메서드로 선언
  • 인스턴스 필드를 이용하지 않는다면 static 메서드로 선언


final

  • 초기값이 저장되면 프로그램 실행 도중 수정할 수 없다.
    • 필드 선언시 초기화를 하거나 생성자에서 초기화를 수행해야 한다.
    • 그렇지 않으면 컴파일 에러
  • static final로 상수 선언
    • 클래스에만 포함되며 값을 변경할 수 없다.
    • 필드 선언시 초기화를 하거나 static 블럭에서 초기화를 수행해야 한다.
  • 상수 이름은 모두 대문자로 하는 것이 관례
  • final method : 오버라이딩 불가능
  • final class : 상속 불가능


package

  • 클래스를 체계적으로 관리하기 위해 사용
  • 클래스를 유일하게 만들어주는 식별자 역할
  • 컴파일러는 클래스에 포함되어 있는 패키지 선언을 보고 파일 시스템의 폴더를 자동 생성
  • 모두 소문자로 하는 것이 관례
  • 숫자로 시작하면 안되고, _, $를 제외한 특수문자 사용 불가능
  • java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 사용 불가
  • 보통 회사들 간에 패키지 중복을 피하기 위해 회사 도메인 이름으로 패키지를 만든다.
    • 포괄적인 이름이 상위 패키지가 되도록 도메인의 역순으로 이름을 짓는다.
    • 마지막에는 프로젝트 이름을 붙여주는 것이 관례


'프로그래밍 > JAVA' 카테고리의 다른 글

[JAVA]SuppressWarnings  (0) 2017.05.22
[JAVA]코드 효율성  (0) 2017.05.22
[JAVA] 파일 이름 변경하기  (0) 2017.01.15
[JAVA]VO 정렬하기  (0) 2017.01.03
[JAVA]ArrayList, Array  (0) 2016.07.16
Comments