안녕하세요. 오늘은 JAVA라는 언어의 틀이 되는 객체지향에 대해서 살펴보고,
그 객체지향이라는 것을 실현시켜 주는 여러가지 키워드들에 대해서 살펴보도록 하겠습니다.
객체지향 프로그래밍
- 현실세계는 모두 객체로 이루어져 있다고 보고 컴퓨터에 적용시켜 객체에 속성, 행위등을 부여하는 것입니다.
- 여기서 속성은 해당 클래스의 고유값, 또는 변수등입니다.
- 여기서 행위는 해당 클래스의 메서드등이라 볼 수 있습니다.
객체지향언어의 장점
- 코드의 재사용성이 높습니다.
- 새로운 코드를 작성할 때 기존의 코드를 이용하여 쉽게 작성할 수 있습니다.
- 코드의 관리가 용이합니다.
- 코드간의 관계를 이용해서 적은 노력으로 쉽게 코드를 변경할 수 있습니다.
- 신뢰성이 높은 프로그래밍을 가능하게 합니다.
- 제어자와 메서드를 이용해서 데이터를 보호, 올바른 값을 유지하도록 하며 코드의 중복을 제거하고 코드의 불일치로 인한 오동작을 방지.
클래스와 객체
클래스
- 클래스의 정의 : 객체를 정의 해놓은 것
- 클래스의 용도 : 객체를 생성하는데 사용.
객체
- 객체의 정의 : 실제로 존재하는 것. 사물 또는 개념
- 객체의 용도 : 객체가 가지고 있는 기능과 속성에 따라 다릅니다.
- 유형의 객체 : 책상, 의자, 자동차, TV와 같은 사물
- 무형의 객체 : 수학공식, 프로그램 에러와 같은 논리나 개념.
클래스 변수와 인스턴스 변수
1. 클래스 변수는 해당 클래스를 인스턴스 생성 (new
키워드) 를 이용하여 생성하지 않아도 사용 가능한 해당 클래스의 클래스 변수를 말합니다. (ex.static 변수)
2. 인스턴스 변수는 해당 클래스를 인스턴스 생성 (new키워드) 후 사용 가능한 변수 입니다. (ex. 참조변수.변수명)
- 클래스 변수: 모든 인스턴스에 공통으로 적용돼야 하는 변수. 보통 생산된 물품의 serialNo 등이 있습니다.
- 인스턴스 변수: 기본적으로 해당 인스턴스의 속성 (TV로 예를 들면 채널, 볼륨 등) , 보통 캡슐화합니다.
상속 (extends)
-
상속의 정의와 장점.
-
기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것입니다.
-
상속을 통해서 클래스를 작성하면 적은 양의 코드로 새로운 클래스를 작성할 수 있고 코드를 공통적으로 관리가능합니다 왜나하면, 공통적인 메서드,변수 등을 조상클래스에서 바꿔만 주면 상속받은 클래스에 영향을 끼치기 때문입니다.
-
조상클래스에 코드가 추가되면 자손클래스에선 영향을 받지만 자손클래스는 상속받은 메서드 등을 바꾸더라도 조상 클래스에 영향을 주지 않습니다.
-
생성자 초기화 블럭은 상속되지 않습니다.맴버만 상속됩니다.
-
자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버와 자손 클래스의 멤버가 합쳐진 하나의 인스턴스로 생성됩니다. (super()를 통해 조상 클래스의 생성자를 호출하기 때문입니다. 자세한 부분은 JVM 포스팅 글에서 명세하도록 하겠습니다.)
-
상속관계와 포함관계
- 상속관계 : '~는 ~이다'.
ex) 나무는 식물이다. 그러므로 나무는 식물의 자손이다.
- 포함관계 : '~는 ~를 가지고 있다' ex) 티비는 채널을 가지고 있다. 그러므로 채널은 티비의 포함관계이다.
-
오버라이딩
- 오버라이딩이란 method declare(선언) 시
@Override
라는 어노테이션 (annotation)을 붙여도 컴파일시 오류가 나지 않는 메서드 정의 방법입니다. (혹은 IDE에서 캐치하거나)
- 더 자세한 표현으로는 조상클래스를 자손이 상속받을때, 조상클래스에 있는 메서드와 이름이 같다면 오버라이딩입니다. (또한 매개변수,반환타입 등의 조건이 있습니다.)
- 오버라이딩의 가장 중요한 점은 다형성이라는 점입니다. 조상클래스 타입의 참조변수를 대입연산자를 통해서 자손클래스의 인스턴스를 생성하면, 조상클래스 타입의 참조변수를 통해 오버라이딩된 자손클래스의 메서드를 호출하게 됩니다. 다형성은 다음 포스팅글에서 명세하겠습니다.
- ex)
Machine machine = new Computer();
-> Machine 이라는 조상클래스를 상속받은 Computer 인스턴스 생성.
- 참조변수를 통한 메서드 호출시 (
machine.메서드명
) 오버라이딩 된 메서드 호출됨.
오버라이딩의 조건
- 이름이 같아야 합니다.
- 매개변수가 같아야 합니다.
- 반환타입이 같아야 합니다. (자손 타입으론 반환가능)
- 접근 제한자와 예외는
- 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없습니다.
- 접근 제한자 범위는
public
> protected
> default
> private
- 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없습니다.
static 참고
static
은 그냥 해당 클래스에만 정의하고, 묶여있다고 생각할 것 !!
자세한 사항은 static
과 non-static
차이점을 따로 포스팅 하도록 하겠습니다.
this, super
들어가기 앞서 인스턴스란?
인스턴스란.
class
를 new
키워드로 해당 class
의 생성자를 호출했을 때,
JVM Runtime Data Area
에 할당됩니다. 이를 인스턴스라 부릅니다.
좀 더 쉽게 설명하자면, class
는 설계도, 인스턴스
는 제품 그 자체라 보면 될 것 같네요.
this
는 현 클래스를 통해 생성된 인스턴스 주소값(포인터)입니다.
super
는 현 클래스의 조상 클래스의 인스턴스 주소값(포인터)입니다.
- 그러므로 자손 클래스로 인스턴스를 생성하면 동시에 부모 클래스의 인스턴스도 생성하므로 당연히
super
, this
를 통하여 인스턴스 주소를 구분할 수 있습니다.
- ex) 자손클래스에서
super
를 통한 부모의 메서드 혹은 멤버필드를 참조할 수 있습니다.
- 자손 클래스에선 조상 클래스의 생성자가 반드시 호출이 되어야 합니다.
- 그러므로 생성자를 호출할때 조상클래스의
default constructor
(super()
) 가 없다면 없다면 다른 생성자를 호출해야합니다. ex) super(x,y)
등과 같은
- 만약 조상클래스의 생성자가 없다면 당연히 기본 생성자를 컴파일러가 자동으로 추가해주기 때문에 컴파일러가 자동으로
super()
를 호출해줍니다.
또한 언급했듯 캡슐화란.
캡슐화(영어: encapsulation)는 객체 지향 프로그래밍에서 다음 2가지 측면이 있다
객체의 속성(data fields)과 행위(메서드, methods)를 하나로 묶고, 실제 구현 내용 일부를 외부에 감추어 은닉한다.
참고 : https://ko.wikipedia.org/wiki/%EC%BA%A1%EC%8A%90%ED%99%94
이며, 보통 외부에서 접근하지 못하게 막는 것을 말합니다.
보통 private을 쓰며 private는 제어자라 합니다.
JAVA에서의 제어자를 설명하도록 하겠습니다.
제어자(modifier)
- 제어자란?
public, protected, default, private
static, final, abstract, native, transient, synchronized, volatile, strictfp
static
- 클래스의, 공통적인
static
멤버 변수는 인스턴스에 관계없이 같은 값을 갖습니다. 하나의 변수를 모든 인스턴스가 공유합니다.
final
- 마지막의, 변경될 수 없는
- 변수에 사용하면 값을 변경할 수 없는 상수가 됩니다.
- 메서드에 사용되면 오버라이딩을 할 수 없게 됩니다.
- 클래스에 사용되면 자신을 확장하는 자손클래스를 정의하지 못합니다.
상수(常數, constant)란 수식에서 변하지 않는 값을 뜻한다. 이것은 변하는 값 변수와 반대이다.
참조 : https://ko.wikipedia.org/wiki/%EC%83%81%EC%88%98
abstract
- 추상의, 미완성의
- 클래스에 사용하면 내부에 추상메서드가 존재하는 것을 알립니다.
- 추상 메서드란 말 그대로 추상적인 상태로써 선언부만 있고 구현부는 없는 메서드를 말합니다.
- 메서드에 사용하면 구현부가 작성되지 않음을 알립니다.
- 접근 제어자 (access modifier)
private
: 같은 클래스내에서만 접근 가능합니다.
default
: 같은 패키지내에서만 접근 가능합니다.
protected
: 같은 패키지 내에서, 그리고 다른 패키지의 자손 클래스에서 접근 가능합니다.
public
: 접근 제한이 없습니다.
- 접근 제어자를 이용한 캡슐화
- 클래스나 멤버, 주로 멤버에 접근 제어자를 사용합니다.
- 해당 이유는 내부에 선언된 데이터를 보호하기 위해서입니다.
- 이를 데이터 감추기 , 객체지향개념의 캡슐화라 합니다.
- 클래스내에서만 사용되는 멤버변수 또는 메서드를 클래스 내부에 감추기 위함입니다.
다형성
- 객체지향개념에서 다형성이란 '여러 가지 형태를 가질 수 있는 능력'이라 합니다.
- 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 프로그램적으로 구현하였습니다.
- 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 합니다.
- 조상 인스턴스 멤버 개수는 자손 인스턴스 멤버 개수보다 항상 적거나 같습니다.
- 서로 형변환 ( 캐스팅 ) 이 가능합니다.
- 업 캐스팅 ( 자손 인스턴스 → 조상 인스턴스 ) 만 생략 가능합니다.
- 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 허용되지 않습니다.
- 그래서 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요합니다.
instanceof 연산자
- 어떤 타입에 대한
instanceof
연산의 결과가 true
라는 것은 검사한 타입으로 형변환이 가능하다는 것을 뜻합니다.
참조변수와 인스턴스의 연결
- 조상 클래스의 멤버변수와 자손 클래스의 멤버변수가 같을시
- 인스턴스의 참조변수의 타입에 따라 달라집니다.
추상화와 구체화
- 추상화 : 클래스간의 공통점을 찾아내서 공통의 조상을 만드는 작업
- 구체화 : 상속을 통해 클래스를 구현, 확장하는 작업
추상클래스
- 자손 클래스에서 추상메서드를 반드시 구현하도록 강요하는 것이라 볼 수 있습니다.
인터페이스
- 일종의 추상클래스입니다.
- 추상화 정도가 높아서 오직 추상메서드와 상수만을 멤버로 가질 수 있습니다.
- 다른 클래스를 작성하는데 도움 줄 목적으로 작성.
- 모든 멤버변수는
public static final
를 붙여야 하며, 생략 가능합니다.
- 모든 메서드는
public abstract
를 붙여야하며 생략 가능합니다.
리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다!!
인터페이스의 장점
- 개발시간을 단축시킬 수 있습니다.
- 일단 인터페이스가 작성되면 이를 사용해서 프로그램을 작성하는 것이 가능합니다. 메서드를 호출하는 쪽에서는 선언부만 알면 되기 때문입니다. 다른 쪽에서는 인터페이스를 구현하는 클래스를 작성하게 되면 양쪽에서 동시에 개발 진행이 가능.
- 표준화가 가능합니다.
- 기본 틀을 인터페이스로 작성한 다음, 개발자들에게 인터페이스를 구현하여 프로그램을 작성하도록 함으로써 일관되고 정형화된 프로그램 개발 가능
- 서로 관계없는 클래스들에게 관계를 맺어줄 수 있습니다.
- 아무런 관계도 없는 클래스에게 인터페이스를 공통적으로 구현하게 함으로써 관계를 맺어 줄 수 있습니다.
- 독립적인 프로그래밍이 가능합니다.
- 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제 구현에 독립적인 프로그램을 작성하는 것이 가능하다. 클래스와 클래스간의 직접적인 관계를 인터페이스를 이용해서 간접적인 관계로 변경하면, 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능합니다.
인터페이스의 이해
- 클래스를 사용하는 쪽(User)과 클래스를 제공하는 쪽(Provider)이 있다면,
- 메서드를 사용(호출)하는 쪽(User)에서는 사용하려는 메서드(Provider)의 선언부만 알면 됩니다.(내용은 몰라도됨)
인터페이스의 디폴트 메서드
- 인터페이스의 다수의 구현체 클래스들이 있다면, 인터페이스에 메서드를 추가하게 되면 많은 구현체 클래스에서 모두 메서드를 구현해야만 한다.
- 그래서 디폴트메서드 (default method) 가 나왔는데, 디폴트메서드는 인터페이스의 기본 제공 메서드 이므로, 구현하지 않아도 됩니다.
- 하지만 만약 인터페이스 ← 부모 ← 자식 (상속도를 표현) 이라는 개념이 있을때, 만약 디폴트메서드와 이름이 중복된다면 부모클래스 메서드를 따릅니다.
내부클래스
- 장점 : 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근가능하다.
- 코드의 복잡성을 줄일 수 있다 (캡슐화)
- 외부 클래스의 멤버변수를 그냥 접근가능하다.
- 당연히 static 과 인스턴스 멤버의 성질에 대해 똑같이 성립한다 예를 들면 static이 붙은 멤버는 인스턴스가 생성되지 않아도 존재할 수 있기 때문에 인스턴스를 생성하고 접근해야하고, 인스턴스 멤버에선 static 멤버를 그냥 접근가능하다.
여기까지 OOP, JAVA기초에 대해서 조금이나마 살펴봤습니다.
객체지향에 대해서 자바에선 클래스, 변수, 메서드, 추상화 등 개념들이 있으며
그에 대한 기본 개념에 대해서 알아봤습니다.
아직 자바에 대해 깊게 알지는 못하지만, 다음 포스팅 예정 글은
non-static, static
lambda, stream
Generics, enums, annotation
jdk 버전별 api 추가사항, 수정사항
으로 계획하고 있습니다!
제 글이 누군가에게 도움이 된다면 좋겠네요~ 감사합니다.
참조 : 자바의 정석