코드스테이츠 15일차

안형준·2022년 5월 17일
0

코드스테이츠

목록 보기
15/32
post-thumbnail

오늘은 객체지향에 대한 개별적 추가 학습, 블로깅에 대해 공부했다.
블로깅에 대한 말은 뒤에서 할 예정으로 먼저 요 며칠동안 정리했던 객체지향에 대한 메모를 정리 할 생각이다.

👻객체지향 언어
1.  빠른 변화에 대한 해결책으로 객체지향 언어를 도입 (절차 -> 객체지향)
2. 코드의 재사용성이 높음, 유지보수가 용이, 중복 코드 제거
3.  객체지향 언어 = 프로그래밍 언어 + 객체지향개념(규칙)

👻객체지향 핵심개념
1. 캡슐화
2. 상속
3. 추상화
4. 다형성

👻클래스 = 제품 설계도
객체 = 제품

👻클래스
- 객체를 정의해 놓은 것
- 객체를 생성하기 위해 필요함

👻객체
- 실제로 존재하는 것, 사물 또는 개념
- 객체 = 속성(변수) + 기능(메서드)
- 객체를 사용하기 위해서 필요함
- 객체를 사용한다는 것은 객체의 속성과 기능을 사용하는 것

👻한 파일에 여러 클래스 작성하기
- 하나의 소스파일에 여러 클래스를 작성할 수 있다.
- 소스파일의 이름은 pulbic class와 같아야 함 (하나의 소스파일엔 하나의 public 클래스만 허용)
- public class가 없는 경우 아무 class의 이름과 같아도 됨
- 소스파일과 클래스의 이름은 대소문자까지 같아야 함
- 하나의 소스파일에는 하나의 클래스만 작성하는 것이 바람직


👻객체의 생성과 사용
1. 클래스 작성
2. 변수 선언 (Tv t;)
3. 객체 생성 (t = new Tv();)
4. 변수를 사용해 객체 사용(변수, 메서드 호출) (t.channel = 7;)

- Tv t = new Tv();
    -> Tv 객체가 만들어지면 t 변수에는 Tv 객체의 주소 값이 저장됨
- 하나의 변수는 객체 하나의 주소만 저장할 수 있지만 하나의 객체는 여러 변수가 참조할 수 있음
- 만약 참조변수 t1, t2를 =를 통해 동일하게 설정한다면, t2가 가리키는 객체는 t1과 같아지기 때문에 기존에 있던 t2가 가리키던 객체는 사용불가하기 때문에 가비지 컬렉터를 통해 삭제된다.

👻객체배열
- 객체 배열 == 참조변수 배열
- 참조변수 배열을 생성한다고 해서 각 변수마다 객체가 생성되는 것이 아니므로 직접 객체를 생성해서 대입해주어야 한다.

👻클래스의 정의
클래스는 3가지로 정의할 수 있다.
①설계도 ②데이터+함수 ③사용자 정의 타입

-②데이터+함수
--변수(하나의 데이터)→배열(같은종류만 저장 가능)→구조체(서로 관련된 여러종류의 데이터만 저장 가능)→클래스(구조체+함수)
--서로 관련되어 있는 데이터, 함수를 같이 사용할 수 있다는 장점이 있다.

-③사용자 정의 타입
--원하는 타입을 직접 만들 수 있음
--서로 관련된 데이터를 하나로 묶어서 객체지향적인 코드로 만들 수 있음

👻선언위치에 따른 변수종류
- 클래스 영역: 인스턴스 변수(iv), 클래스 변수(cv = static + iv)
- 메서드 영역: 지역변수(lv)
- 클래스 영역에는 선언문만 가능함

- 객체 = iv를 묶어놓은것 (프로그래밍 관점)

- 인스턴스 변수는 객체가 생성될 때 만들어짐
- 클래스 변수는 클래스가 메모리에 올라갈 때 한 번만 만들어짐
- 지역변수는 변수가 선언되면 생성돼서 메서드 종료 시 자동 제거

👻클래스 변수와 인스턴스변수
- 객체마다 다르게 유지되어야 하는 값 -> 인스턴스 변수
- 객체마다 공통된 값 -> 클래스 변수
- 클래스 변수는 객체 생성없이 사용가능
- 인스턴스 변수는 객체 생성 후 사용가능

👻메서드란? 메서드의 선언부와 구현부
메서드
- 값을 받아 처리하고, 결과를 반환
- 반복적으로 수행되는 문장을 메서드로 작성 (코드의 중복을 제거)
- 하나의 메서드는 한 가지 기능만 수행하도록 작성
- 메서드 출력 값이 없을 때에는 void타입을 사용한다.

지역변수는 메서드 안에서만 사용되고, 그 메서드가 종료됨에 따라 함께 종료되기 때문에 다른 메서드의 지역변수에서도 동일한 변수 이름을 사용할 수 있다.

👻메서드호출
- 메서드를 정의했어도 호출되지 않으면 아무 일도 일어나지 않는다.
- 반환 값이 있는 메서드의 경우 해당 결과를 저장할 변수가 필요함 (따로 변수에 대입하지 않으면 호출만 되고 끝남)

👻return문, 반환값
return문
- 실행 중인 메서드를 종료하고 호출한 곳으로 돌아감
- 반환타입이 void가 아닐 때 return 문을 생략할 수 없음
- 반환타입이 void가 아니고, 메서드 내에 조건문이 있을 때 해당 조건의 모든 경우(true에 return이 있다면 false에도 return이 존재해야함)에 return문이 존재해야 함
- return값은 반환타입과 일치해야 한다. (자동형변환이 가능하다면 다른 타입도 가능)

👻호출스택
스택
- 밑이 막힌 상자라고 생각한다면, 위로 하나씩 담길거고 위에 있는 메서드가 실행되는 동안에는 아래에 있는 메서드는 대기 상태로 바뀐다. 
- 위에 있는 메서드가 종료될 시 스택에서 제거되며, 아래에 있는 메서드가 실행 상태로 바뀐다.
호출 스택
- 메서드 수행에 필요한 메모리가 제공되는 공간
- 메서드가 호출되면 호출스택에 메모리 할당, 종료되면 제거
- 스택의 아래쪽 메서드가 위의 메서드를 호출한 것
- 스택 맨 위 메서드 하나만 실행 중, 나머지는 대기중

👻기본형 매개변수
- 기본형 매개변수 : read only
- 참조형 매개변수 : read & write
- 변수의 값을 읽기만 할 수 있음(read only)

👻참조형매개변수, 참조형 반환타입
참조형 매개변수
- 변수의 값을 읽고 변경할 수 있음(read & write)
- 매개변수로 참조형 변수를 전달할 경우 변수가 가리키는 객체의 주소 값이 전달됨
- 매개변수로 전달된 변수와 같은 객체를 가리키기 때문에 값의 변경이 가능함

참조형 반환타입
- 반환 값으로 객체의 주소 값을 전달함

즉, 기본형 매개변수에서는 가리키고 있는 값을 그냥 줬다면 참조형 매개변수에서는 어디에 저장되어 있는지 객체 주소를 전달해줬기 때문에 객체를 다룰 수 있게 된다.

👻static메서드와 인스턴스 메서드

인스턴스 메서드
- 인스턴스 생성 후 참조변수.메서드() 방식으로 호출
- 인스턴스 멤버(iv, im)와 관련된 작업을 하는 메서드
- 메서드 내에서 iv사용가능

static(class) 메서드
- 객체 생성없이 클래스이름.메서드이름()
- 인스턴스 멤버(iv, im)와 관련없는 작업을 하는 메서드
- 메서드 내에서 iv 사용불가

- 메서드 간의 호출, 참조 : static메서드는 인스턴스 변수(iv)를 사용할 수 없다.
왜?
static메서드는 객체 생성 없이 사용 가능한데, iv는 객체가 생성되어야만 사용 가능하다. 즉, 객체가 생성이 안되었을 수도 있어서

👻오버로딩
오버로딩
- 한 클래스 안에 같은 이름의 메서드를 여러 개 정의하는 것

조건
- 메서드 이름이 같아야 함
- 매개변수의 개수 또는 타입이 달라야 함
- 반환 타입과 매개변수의 이름은 영향이 없음

👻생성자, 기본 생성자
생성자
- 인스턴스 초기화 메서드
- 인스턴스 생성 시 수행할 작업에 사용
- 생성자 오버로딩 가능
- 항상 리턴값이 없음 (void 안붙임)
- 생성자의 이름은 클래스 이름과 같아야 한다.
- 모든 클래스는 반드시 1개 이상의 생성자를 가져야한다.

- 매개변수가 있는 생성자 작성 시 기본 생성자도 같이 작성해주는 것이 안전
    -> 클래스에 생성자가 하나라도 존재하면 컴파일러가 기본 생성자를 자동으로 추가해주지 않기 때문에

기본생성자
클래스이름(){}
-매개변수가 없는 생성자
-생성자가 하나도 없을 때는 컴파일러가 자동으로 추가해준다. (만약 존재한다면 생성X)

👻생성자 this(), 참조변수 this
생성자 this()
- 생성자에서 다른 생성자 호출할 때 사용
- 생성자의 첫 줄에서만 사용가능
- this()를 사용하여 코드의 중복을 제거할 수 있음

참조변수 this
- 인스턴스 자신을 가리키는 변수
- 인스턴스 메서드(생성자 포함)에서 사용가능
- 지역변수와 인스턴스 변수를 구별할 때 사용함
    -> 지역변수와 인스턴스 변수의 이름이 같은 경우 this를 생략할 수 없음 (이름이 다르면 생략가능)
- static 메서드에서는 사용 불가능
   -> static 메서드가 사용되는 시점에 객체가 생성되었는지 확신할 수 없기 때문에(static 멤버는 객체 생성없이도 사용이 가능하기 때문) 사용 불가능함

* this와 this()는 완전히 다른 것

👻변수의초기화, 멤버변수의 초기화
초기화 순서
1. 클래스(cv) 초기화
    1-1. 기본 값(자동)
    1-2. 명시적 초기화(=를 사용하여 간단하게)
    1-3. 클래스 초기화 블럭 (static{ })(복잡)
2. 인스턴스(iv) 초기화
    2-1.기본 값(자동)
    2-2. 명시적 초기화(=를 사용하여 간단하게)
    2-3. 인스턴스 초기화 블럭(복잡)
    2-4. 생성자(복잡)

👻상속
- 자손은 조상의 모든 멤버를 상속 받음(생성자, 초기화 블럭 제외)
- 자손의 멤버 개수는 조상보다 많거나 같음
- 자손의 변경은 조상에 영향을 미치지 않음
- class 자손 extends 조상 { }

👻클래스 간의 관계, 상속과 포함
포함 관계
- 클래스의 멤버로 참조변수를 선언하는 것

관계를 결정하는 간단한 방법
- 상속관계: ~은 ~이다.(is-a)
- 포함관계: ~은 ~을 가지고 있다.(has-a)

👻단일상속, Object클래스
단일 상속
- 조상을 하나만 허용하는 것
- 여러 조상을 상속받을 경우 같은 이름의 변수, 메소드 충돌이 발생할 여지가 있어 다중 상속을 사용하지 않음

- 다중상속의 효과를 내는 방법으로 비중이 높은 클래스 하나를 상속관계로 설정하고, 나머지는 포함관계로 설정하는 것

Object 클래스
- 모든 클래스는 Object 클래스를 상속받음(모든 클래스의 조상)
- 조상이 없는 클래스는 자동으로 상속받음

👻오버라이딩
- 상속받은 조상의 메서드를 자신에 맞게 내용을 변경하는 것
- 선언부 변경불가 / 내용만 변경가능

오버라이딩 조건
- 선언부가 조상 클래스의 메서드와 일치 (반환타입, 메서드이름, 매개변수 목록)
- 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없음
- 예외는 조상 클래스의 메서드보다 많이 선언할 수 없음

오버로딩 vs 오버라이딩
- 오버로딩 : 기존에 없던 새로운 메서드 정의
- 오버라이딩 : 상속 받은 메서드 내용을 자신에 맞게 내용 변경

👻참조변수 super, 생성자 super()
참조변수 super
- 객체 자신을 가리키는 참조변수, 인스턴스 메서드(생성자 포함)내에만 존재
- 조상 멤버와 자신의 멤버가 중복되는 경우에 구별할 때 사용
    -> 조상의 멤버: super.x / 자신의 멤버: this.x

조상의 생성자 super()
- 자손이 조상의 생성자를 호출할 때 사용
- 조상의 멤버는 조상의 생성자가 초기화 하도록 해야 함
    -> 조상의 멤버를 어떻게 초기화해야 할지 가장 잘 아는 것은 조상이기 때문에
- 생성자의 첫 줄에 반드시 생성자를 호출해야 함
- 첫 줄에 생성자가 호출되지 않으면 컴파일러가 super()을 삽입

👻패키지, 클래스 패스
패키지
- 서로 관련된 클래스의 묶음
- 클래스 -> 클래스 파일(*.class), 패키지는 폴더
- 실제로 클래스의 full name은 패키지를 포함

패키지 선언
- 패키지는 소스파일의 첫 번째 문장으로 단 한 번 선언
- 패키지 선언이 없으면 디폴트 패키지에 속하게 됨

클래스패스
- 클래스파일의 위치를 알려주는 경로
- 환경변수 classpath로 관리 : 패키지의 루트를 환경변수에 등록해주면 콘솔창에서 패키지를 찾을 때 환경변수에 등록된 경로를 확인하므로 패키지가 있는 폴더까지 이동하지 않아도 확인할 수 있다.

👻import문, static import문
import 문
- 클래스를 사용할 때 패키지 이름을 생략할 수 있음
- 컴파일러에게 클래스가 속한 패키지를 알려줌
- 패키지 문과 클래스 선언 사이에 위치함
- 컴파일 시에 처리되므로 프로그램의 성능에 영향없음

static import문
- static 멤버를 사용할 때 클래스 이름을 생략할 수 있게 해줌

👻제어자 static, final, abstract
제어자
- 클래스와 클래스의 멤버에 부가적인 의미 부여
- 하나의 대상에 여러 제어자를 같이 사용가능(접근 제어자는 하나만)

접근 제어자: public, protected, (default), private

static: 클래스의, 공통적인
- 멤버변수, 메서드에 붙일 수 있음

final: 마지막의, 변경될 수 없는
- 클래스 -> 변경될 수 없는, 확장될 수 없는 클래스(다른 클래스의 조상이 될 수 없음)
- 메서드 -> 변경될 수 없는 메서드(오버라이딩 불가)
- 변수 -> 값을 변경할 수 없는 상수

abstract: 추상의, 미완성의
- 클래스 -> 클래스 내에 추상 메서드가 선언되어 있음을 의미
- 메서드 -> 선언부만 작성하고, 구현부는 작성하지 않은 추상 메서드
- 추상 메서드는 미완성 -> 추상 클래스 또한 미완성
   -> 미완성 설계도는 제품 생성이 불가능하기 때문에 객체 생성이 불가능함(상속을 통해 완성된 설계도로 객체 생성가능)

👻접근제어자
-한개만 사용가능

public : 접근 제한 없음
protected : 같은 패키지내 + 다른패키지 자손
(default) : 같은 패키지 내 접근 가능
private :  같은 클래스 내에만 가능

클래스에는 + public / (default) 만 가능
메소드에는 4개 다 사용가능

👻캡슐화
- 외부로부터 데이터를 보호하기 위해 접근 제어자 사용
- 외부엔 불필요하고 내부적으로 사용되는 데이터를 감추기 위해 사용
- 잘못된 데이터가 저장되는 것을 막기 위해 직접 접근보다는 메서드를 통한 간접 접근을 허용

👻다형성
- 조상 타입 참조변수로 자손 타입 객체를 다루는 것

- 객체와 참조변수의 타입이 일치하지 않을 때
    -> 참조변수와 객체의 타입이 일치하는 경우, 객체의 모든 멤버를 다룰 수 있음, 조상 객체로 자손 객체를 다루는 경우 조상이 가진 멤버만을 다룰 수 있음
- 자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없음
    -> 자손이 다룰 수 있는 기능보다 부모가 가진 멤버가 적기 때문에 참조변수가 객체에 존재하지 않는 기능을 호출하는 경우 에러 발생

👻참조변수의 형변환
- 참조변수의 형변환 -> 사용할 수 있는 멤버의 개수를 조절
- 상속관계 참조변수는 서로 형변환 가능
- 자손 -> 조상 사용 멤버의 개수 감소 (안전하므로 괄호 생략 가능)
- 조상 -> 자손 사용 멤버의 개수 증가 (안전하지 않아 괄호 생략 불가)
- 형변환 시 실제 객체가 무엇인지가 중요함
    -> 실제 객체보다 참조변수의 멤버가 더 많다면 에러가 발생할 수 있어 위험

👻instanceof 연산자
instaneof 연산자
- 참조변수의 형변환 가능여부 확인에 사용(true / false)
- 객체의 모든 조상에 대해서 참 반환
- 참조변수를 변경함으로써 사용할 수 있는 멤버의 개수 조절가능

👻매개변수 다형성
- 직접 형변환 할 때 형변환의 과정 : 1) 확인(형변환 해도 되는지 체크 -> instanceof 연산자를 이용하여) 2) 형변환

- 다형성의 장점
1) 다형적 매개변수 2) 하나의 (객체)배열로 여러가지 종류의 객체 다루기

- 다형성
1) Tv t = new SmartTV();
2) 참조변수의 형변환 -> 리모콘 바꾸기, 사용가능한 iv 갯수 조절
3) instanceof 연산자 -> 형변한 가능 체크 기능

- 참조형 매개변수는 메서드 호출 시 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.

- ex) Product(부모) - Computer(자식) 관계이고

Buyer 클래스에  void buy(Product p)라는 메서드가 정의되어 있을 때

[1] Buyer b = new Buyer();
[2] Product p = new Tv1();
[3] b.buy(p);와 
[2], [3] 과 같은 것은 b.buy(new Tv1()) // 익명클래스 이용하여 한줄로 가능

👻추상 클래스, 추상 메서드
추상 클래스(abstract class)
- 미완성 설계도, 미완성(추상) 메서드를 가진 클래스
- 구현부가 없는 메서드
- 인스턴스 생성이 불가능
    -> 미완성 설계도이기 때문에 제품 생성이 불가능
- 상속을 통해 추상 메서드를 완성해야 인스턴스 생성이 가능함

추상 메서드
- 미완성 메서드, 구현부가 없음
- abstract 리턴타입 메서드이름();
- 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상될 때 사용함
- 인스턴스 메서드에서 추상 메서드를 사용할 수 있음
    -> 인스턴스 메서드가 호출되기 위해서는 인스턴스가 생성되야 하기 때문에 가능함 (추상 메서드가 완성되어야 인스턴스가 생성 가능)

👻추상 클래스의 작성
추상 클래스
- 여러 클래스에 공통적으로 사용될 수 있는 부분을 뽑아서 추상 클래스를 작성함
- 공통 부분을 추출함으로써 코드가 간결해지고 중복이 제거됨

추상 클래스를 사용하면 좋은 점은?
- 작성이 쉬움
- 관리(변경)이 용이함
- 중복이 제거됨

추상화 <-> 구체화
- 추상화된 코드는 구체화된 코드보다 유연함 -> 변경에 유리

👻인터페이스의 선언, 상속, 구현
인터페이스
- 추상 메서드의 집합(프로그래밍 관점)
- 구현된 것이 전혀 없는 설계도 (모든 멤버가 public)
- 변수로 상수만을 가질 수 있음(물론 예외는 있긴하다. public static final)
- 메서드 선언 시 abstract 생략가능
- 인터페이스의 조상은 인터페이스만 가능
- 다중 상속이 가능함 -> 추상 메서드는 충돌해도 문제가 없음
- 조상과 후손에 같은 이름의 상수 값이 존재하면 덮어씌워짐
- implements 키워드 사용해 구현할 인터페이스 명시
- 인터페이스 구현 -> 인터페이스에 정의된 추상 메서드를 완성하는 것

추상 클래스와 인터페이스 차이점
- 추상 클래스는 일반 클래스이지만 추상 메서드를 가진 클래스이고, 인터페이스는 구현된 것이 아무것도 없이 추상 메서드만 가짐

👻인터페이스와 다형성
- 인터페이스 참조변수로 인터페이스를 구현한 인스턴스를 참조할 수 있음 (다형성)
    -> 인터페이스에 정의된 메서드만 접근이 가능함
- 인터페이스 타입의 매개변수는 인터페이스 구현한 클래스의 객체를 매개변수로 제공해야 함
- 인터페이스를 메서드의 리턴타입으로 지정할 수 있음
    -> 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미

👻인터페이스의 장점
인터페이스의 장점
- 두 대상(객체) 간의 연결, 대화, 소통을 돕는 중간 역할
- 사람 -> 껍데기(인터페이스) -> 기계
- 인터페이스의 구현 내용이 변경되어도 인터페이스가 동일하다면 사용자는 영향을 받지 않음 (변경에 유리, 느슨한 결합)
- 선언(설계)와 구현을 분리시킬 수 있음
- 개발 시간을 단축할 수 있음
    -> 실제 구현내용이 없어도 인터페이스가 만들어져 있으면 사용자는 메서드를 호출할 수 있음
 - 변경에 유리한 유연한 설계가 가능
- 표준화가 가능함
    -> ex) JDBC: 데이터베이스가 변경되어도 애플리케이션은 거의 변경이 없음
- 서로 관계없는 클래스들을 관계를 맺어줄 수 있음
    -> 서로 관계없는 클래스가 같은 인터페이스를 구현하도록 만들어 관계를 맺어줄 수 있음

👻디폴트 메서드와 static메서드
Jdk 1.8이상부터 인터페이스에 default 메서드(인스턴스 메서드)와 static 메서드 추가가능
-인터페이스에 새로운 메서드를 추가하면 이 인터페이스를 구현한 모든 클래스에서 새로운 메서드를 구현해야하는 어려움이 있어 나온 대안이다.

- 다른 메서드가 기존의 메서드와 충돌될 때 해결책
1) 여러 인터페이스의 디폴트 메서드간 충돌 : 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 함
2) 디폴트 메서드와 조상 클래스의 메서드 간의 충돌 : 조상 클래스의 메서드가 상속, 디폴트 메서드는 무시
(그냥 직접 오버라이딩 하면 해결)

이번에 객체지향을 학습하면서 너무 많은 것들을 배운 탓인지 정리 되지 않은 기분이 들어 앞으로도 객체지향에 대해 지속적으로 복습을 하면서 깔끔하게 정리를 해야겠다는 생각이 들었다.
또한 블로깅에 대한 중요성은 원래도 알고 있었지만 그림, 예시코드 등을 활용하여 좀 더 깔끔하고 생산성 있는 블로그를 만들 수 있다는 점을 깨달았다.
앞으로 꾸준히 공부하면서 누군가에게 설명할 수 있는 수준이 되었을 때 내가 이 개념을 완벽히 이해하기까지 어떤 어려움이 있었을까?를 생각하며 초심자 입장에 맞추어 포스트를 작성 할 생각이다.
오늘도 고생 많았고 내일도 파이팅!

profile
개발 공부

0개의 댓글