자바는 클래스랑 객체로 이루어짐
왜 필요 할까..
타입은 데이터의 종류나 형태를 나타낸다.
int
라고 하면 정수 타입, String
이라고 하면 문자 타입이다.
학생( Student
)이라는 타입을 만들면 되지 않을까?
클래스를 사용하면 int
, String
과 같은 타입을 직접 만들 수 있다.
사용자가 직접 정의하는 사용자 정의 타입을 만들려면 설계도가 필요하다. 이 설계도가 바로 클래스이다.
설계도인 클래스를 사용해서 실제 메모리에 만들어진 실체를 객체 또는 인스턴스라 한다.
클래스는
String name,
int age,
int grade` 멤버 변수를 가지고 있다. 이 변수를 사용하는 데 필요한 메모리 공간도 함께 확보한다.객체를 생성하면 자바는 메모리 어딘가에 있는 이 객체에 접근할 수 있는 참조값(주소)( x001
)을 반환한다.
new
키워드를 통해 객체가 생성되고 나면 참조값을 반환한다. 앞서 선언한 변수인 Student student1
에 생 성된 객체의 참조값( x001
)을 보관한다
Student student1
변수는 이제 메모리에 존재하는 실제 Student
객체(인스턴스)의 참조값을 가지고 있 다.
student1
변수는 방금 만든 객체에 접근할 수 있는 참조값을 가지고 있다. 따라서 이 변수를 통해서 객체 를 접근(참조)할 수 있다. 쉽게 이야기해서 student1
변수를 통해 메모리에 있는 실제 객체를 접근하고 사용할 수 있다.new Student()
코드 자체에는 아무런 이름이 없다. 이 코드는 단순히 Student
클래스를 기반으 로 메모리에 실제 객체를 만드는 것이다. 따라서 생성한 객체에 접근할 수 있는 방법이 필요하다. 이런 이유로 객체를 생 성할 때 반환되는 참조값을 어딘가에 보관해두어야 한다. 앞서 Student student1
변수에 참조값( x001
)을 저장 해두었으므로 저장한 참조값( x001
)을 통해서 실제 메모리에 존재하는 객체에 접근할 수 있다Student student1 = new Student(); //1. Student 객체 생성
Student student1 = x001; //2. new Student()의 결과로 x001 참조값 반환
student1 = x001; //3. 최종 결과
student1
)에 들어있는 참조값( x001
)을 읽어서 메모리에 존재하는 객체에 접근한다.student1.name="학생1" //1. student1 객체의 name 멤버 변수에 값 대입
x001.name="학생1" //2.변수에 있는 참조값을 통해 실제 객체에 접근, 해당 객체의 name 멤버 변수에 값
대입
student1
은 x001
이라는 참조값을 가지고 있으므로 x001
위치에 있는 Student
객체에 접근한다.//1. 객체 값 읽기
System.out.println("이름:" + student1.name);
//2. 변수에 있는 참조값을 통해 실제 객체에 접근하고, name 멤버 변수에 접근한다.
System.out.println("이름:" + x001.name);
//3. 객체의 멤버 변수의 값을 읽어옴
System.out.println("이름:" + "학생1");
객체 - Object
객체는 클래스에서 정의한 속성과 기능을 가진 실체이다. 객체는 서로 독립적인 상태를 가진다.
예를 들어 위 코드에서 student1
은 학생1의 속성을 가지는 객체이고, student2
는 학생2의 속성을 가지는 객체이 다. student1
과 student2
는 같은 클래스에서 만들어졌지만, 서로 다른 객체이다.
인스턴스 - Instance
인스턴스는 특정 클래스로부터 생성된 객체를 의미한다. 그래서 객체와 인스턴스라는 용어는 자주 혼용된다. 인스턴스 는 주로 객체가 어떤 클래스에 속해 있는지 강조할 때 사용한다. 예를 들어서 student1
객체는 Student
클래스의 인스턴스다. 라고 표현한다.
객체 vs 인스턴스
둘다 클래스에서 나온 실체라는 의미에서 비슷하게 사용되지만, 용어상 인스턴스는 객체보다 좀 더 관계에 초점을 맞춘 단어이다. 보통 student1
은 Student
의 객체이다. 라고 말하는 대신 student1
은 Student
의 인스턴스이다. 라고 특정 클래스와의 관계를 명확히 할 때 인스턴스라는 용어를 주로 사용한다.
좀 더 쉽게 풀어보자면, 모든 인스턴스는 객체이지만, 우리가 인스턴스라고 부르는 순간은 특정 클래스로부터 그 객체가 생성되었음을 강조하고 싶을 때이다. 예를 들어 student1
은 객체이지만, 이 객체가 Student
클래스로부터 생성되 다는 점을 명확히 하기 위해 student1
을 Student
의 인스턴스라고 부른다.
하지만 둘다 클래스에서 나온 실체라는 핵심 의미는 같기 때문에 보통 둘을 구분하지 않고 사용한다.
Student
타입의 변수는 Student
인스턴스의 참조값을 보관한다. Student
배열의 각각의 항목도 Student
타입의 변수일 뿐이다. 따라서 Student
타입의 참조값을 보관한다.
student1
, student2
변수를 생각해보면 Student
타입의 참조값을 보관한다.
배열에는 아직 참조값을 대입하지 않았기 때문에 참조값이 없다는 의미의 null
값으로 초기화 된다.
이제 참조 값을 보관하자면 ?
students[0] = student1; 이런식으로..
students[0] = x001;
students[1] = x002;
이런식으로 참조값이 보관된다.
자바에서 대입은 항상 변수에 들어 있는 값을 복사해서 전달한다.
students[0] = student1;
students[1] = student2;
//자바에서 대입은 항상 변수에 들어 있는 값을 복사한다.
students[0] = x001;
students[1] = x002;
=
)은 모두 변수에 들어있는 값을 복사해서 전달하는 것이다. 이 경우 오른쪽 변수인student1
, student2
에는 참조값이 들어있다. 그래서 이 값을 복사해서 왼쪽에 있는 배열에 전달한다. 따라서 기존 student1
, student2
에 들어있던 참조값은 당연히 그대로 유지된다.주의!
=
)시에 인스턴스가 복사되는 것이 아니라 참조값만 복사된다.학생1 예제
System.out.println(students[0].name); //배열 접근 시작
System.out.println(x005[0].name); //[0]를 사용해서 x005 배열의 0번 요소에 접근
System.out.println(x001.name); //.(dot)을 사용해서 참조값으로 객체에 접근
System.out.println("학생1");
쉽게 구분하는 기본형과 참조형
but 대문자로 시작하는 String 은 참조형! 클래스이기 때문
int a = 10
int b= a; //a의 값을 복사해서 넣어주기 때문에 복사값이다.
Student s1 = new Student(); // x001 참조값
Student s2 = s1;
// 기본형 -> 해당 값을 복사해서 바로 대입
// 참조값 -> 객체의 위치를 가르키는 참조값만 복사
자바에서 메서드의 매개변수(파라미터는)항상 값에 의해 전달! (중요)
근대 그게 실제 값이냐 ? 참조 값이냐 따라 동작이 다름
기본형 : 종이가 2장있는대 옆사람 종이에게 내가 가진 숫자를 적어 준 것. 옆종이의 값을 바꾼다고 내것이 바뀌는 건 아니지!
참조형: 종이에 주소지가 있음 주소지를 적어서 옆사람에게 전달
옆사람이 주소지 찾아가서 건물에 있는걸 변경
내가 그 주소지를 찾아가면 변경된걸 발견
NULL 에다 점 찍으니 에러가나지!
참조값 예외가 발생하는 과정
말 그대로 객체 지향. 객체가 중요하다
실제 세계의 사물이나 사건을보고 객체들간 상호작용 프로그래밍
흔히 아는 개념..
메서드 추출
각각의 기능이 모듈화가 되었음
중복로직 제거 / 변경 영향 범위: 기능 수정시 메서드 내부만 변경
메서드 이름추가: 메서드의 이름으로 코드를 좀더 쉽게 이해!
위에 작성한 코드는 데이터와 기능이 분리되어 있음,
음악 플레이어 데이터 : MusicPlayerData에 있는데
그 데이터를 사용하는 기능은 MusicPlayerMain3에 있는 각각 메서드의 분리
음악플레이어 관련된 데이터는 MusicPlayerData 사용
음악플레이어 관련된 기능은 MusicPlayerMain3 각 메서드를 사용해야함.
데이터 / 데이터 사용기능은 매우 밀접하게 연관되 있음.
각각의 메서드는 MusicPlayerData의 데이터를 사용, 따라서 이후 데이터 변경시
MusicPlayerMain3 메서드 함께변경,
이런식으로 데이터 / 기능이 분리되어있으면 유지보수관점 포인트가 2곳으로 늘어남
설명을 참잘하신다..
valueObject.add(); //1
x002.add(); //2: x002 ValueObject 인스턴스에 있는 add() 메서드를 호출한다.
데이터와 기능을 클래스에 모두 담아 둠으로서 코드가 모듈화도되면서 가독성이 더 좋아짐
세상의 존재하는 사물을 최대한 클레스로 표현 (멤버와 메서드로 표현)
멤버 변수와 메서드의 매개변수의 이름이 같으면 둘을 어떻게 구분해야 할까?
이 경우 멤버 변수보다 매개변수가 코드 블럭의 더 안쪽에 있기 때문에 매개변수가 우선순위를 가진다. 따라서
initMember(String name,...) 메서드 안에서 name 이라고 적으면 매개변수에 접근하게 된다.
멤버 변수에 접근하려면 앞에 this. 이라고 해주면 된다. 여기서 this 는 인스턴스 자신의 참조값을 가리킨다
생성자 도입 예제
생성자는 인스턴스를 생성하고 나서 즉시 호출된다. 생성자를 호출하는 방법은 다음 코드와 같이 new 명령어 다음에
생성자 이름과 매개변수에 맞추어 인수를 전달하면 된다.
new MemberConstruct("user1", 15, 90)
이렇게 하면 인스턴스를 생성하고 즉시 해당 생성자를 호출한다. 여기서는 Member 인스턴스를 생성하고 바로
MemberConstruct(String name, int age, int grade) 생성자를 호출한다
//생성자 등장 전
MemberInit member = new MemberInit();
member.initMember("user1", 15, 90);
//생성자 등장 후
MemberConstruct member = new MemberConstruct("user1", 15, 90)
생성자의 진짜 장점은 객체를 생성할 때 직접 정의한 생성자가 있다면 직접 정의한 생성자를 반드시 호출해야 한다는 점
이다. 참고로 생성자를 메서드 오버로딩 처럼 여러개 정의할 수 있는데, 이 경우에는 하나만 호출하면 된다
제약...
정리
생성자는 반드시 호출되어야 한다.
생성자가 없으면 기본 생성자가 제공된다.
생성자가 하나라도 있으면 기본 생성자가 제공되지 않는다. 이 경우 개발자가 정의한 생성자를 직접 호출해야 한다
컴퓨터는 보통 파일을 분류하기 위해 폴더, 디렉토리라는 개념을 제공한다. 자바도 이런 개념을 제공하는데, 이것이 바
로 패키지이다
패키지(package)는 이름 그대로 물건을 운송하기 위한 포장 용기나 그 포장 묶음을 뜻한다.
ex) com.company.myapp 이런식 url 도메인 거꾸로
필수는 아니지만 수 많은 외부 라이브러리가 함께 사용되면
같은 패키지에 같은 클래스 이름이 존재할 수있음
이런식으로 거꾸로 사용하면 문제 방지
내가 오픈소스나 라이브러리를 만들어서 외부에 제공하면 지키는게 좋다.
계층 구조를 이루더라도 서로 다른 패키지이다
보이기엔 계층적으로 이루어져 있어도 서로 다른 패키지
그래서 서로 다른 패키지에서 다른 패키지에있는 소스를 사용할 때 import를 사용해야 된다.
private 접근제어자는 모든 외부호출 막음 (클래스 내부에서만 호출 가능)
speaker 안에서 숨어버려서 speaker내부에서만 접근 가능
좋은 프로그램은 적절한 제약을 제공하는 프로그램이다.
private : 모든 외부 호출 막음
default(package-private) : 같은 패키지안에서 호출허용
아무것도 적지않으면 적용됨.
protected 같은 패키지안에서 호출허용/ 패키지달라도 상속관계 호출 허용
public
접근 제어자의 핵심은 속성과 기능을 외부로부터 숨기는 것이다.
- private 은 나의 클래스 안으로 속성과 기능을 숨길 때 사용, 외부 클래스에서 해당 기능을 호출할 수 없다.
- default 는 나의 패키지 안으로 속성과 기능을 숨길 때 사용, 외부 패키지에서 해당 기능을 호출할 수 없다.
- protected 는 상속 관계로 속성과 기능을 숨길 때 사용, 상속 관계가 아닌 곳에서 해당 기능을 호출할 수 없다.
- public 은 기능을 숨기지 않고 어디서든 호출할 수 있게 공개한다
클래스 레벨의 접근 제어자는 public , default 만 사용할 수 있다.
public 클래스는 반드시 파일명과 이름이 같아야 한다.
하나의 자바 파일에 public 클래스는 하나만 등장할 수 있다.
하나의 자바 파일에 default 접근 제어자를 사용하는 클래스는 무한정 만들 수 있다
캡슐화(Encapsulation)는 객체 지향 프로그래밍의 중요한 개념 중 하나다. 캡슐화는 데이터와 해당 데이터를 처리하는 메서드를 하나로 묶어서 외부에서의 접근을 제한하는 것을 말한다.
쉽게 얘기하면 속성과 기능을 하나로 묶고 , 외부에 꼭 필요한 기능만 노출하고 나머지는 모두 내부로 숨기는 것이다
캡슐화를 안전하게 완성해주는 것? 접근제어자
객체는 속성 (데이터) , 기능 (메서드) 있음
1번째는 속성(데이터를) 숨겨야 됨. 객체 내부의 데이터를 외부에서 함부로 접근하게 두면 클래스 안에서 데이터를 다루는 모든 로직 무시하고 데이터 변경. (캡슐화깨짐)
- 우리가 자동차를 운전할 때 자동차 부품을 다 열어서 그 안에 있는 속도계를 직접 조절하지 않는다.
- 단지 자동차가 제공 하는 엑셀 기능을 사용해서 엑셀을 밟으면 자동차가 나머지는 다 알아서 하는 것이다
우리는 자동차를 운전하기 위해 자동차가 제공하는 복잡한 엔진 조절 기능, 배기 기능까지 우리가 알 필요는 없다.
우리는 액셀과 핸들 정도 기능만 알면 됨
가급적 필요한 기능만 오픈하기
메서드 영역: 프로그램을 싱행하는데 필요한 공통데이터 관리
클래스 정보: 클래스 실행코드(바이트 코드), 필드 , 메서드와 생성자 코드등 모든 실행 코드가 존재함.
static 영역: static 변수를 보관
런타임 상수풀: 프로그램 실행하는데 필요한 공통 리터럴 상수 보관.
"hello" 라는 리터럴 문자가 있으면 이런 문자를 공통으루 묶어서 관리
이 외에도 프로그램을 효율적으로 관리하기 위한 상수들을 관리함 (알아만두자)
스택 영역: 자바 실행시 하나의 실행스택이 생성 됨.
각 스택 프로엠은 지역 변수 , 중간연산결과 , 메서드 호출 정보등 포함
스택 프레임 : 스택 영역에 쌓이는 네모 박스가 하나의 스택 프레임.
메서드 호출할 때마다 하나의 스택프레임이 쌓이고 메소드가 종료되면 스택 프레임이 제거 됨.
힙 영역 : 객체 와 배열이 생성되는 영역 , GC 가 이루어지는 영역
참고 : 스택 영역은 더 정확히는 각 쓰레드 별로 하나의 실행 스택이 생성됨.
따라서 쓰레드 수 만큼 스택영역이 생성된다, 지금은 쓰레드 1개만 사용하므로 스택 영역도 하나이다,
각각 본인의 메서드와 변수를 가짐
정리하면 메서드를 호출하면 메서드 영역에 있는 코드를 불러서사용
( 메서드 영역은 프로그램 실행하는데 필요한 공통데이터를 관리하니)
종료 되면서 (unreachable) 상태가 된다
메서드가 종료되면서 지역 변수들이 참조 값을 가지는 애가 없기 때문에 힙 영역 데이터를 가르키지 않기 때문에
GC(가비지 컬렉션)은 이렇게 참조가 모두 사라진 인스턴스를 찾아서 메모리에서 제거한다.
++ : 힙 영역 외부가 아닌, 힙 영역 안에서만 인스턴스끼리 서로 참조하는 경우에도 GC의 대상이 된다
인스턴스를 공통으로 사용하기 때문에 하나씩 증가한다 .
그런데 여기에는 약간 불편한 점들이 있다.
Data2 클래스와 관련된 일인데, Counter 라는 별도의 클래스를 추가로 사용해야 한다.
생성자의 매개변수도 추가되고, 생성자가 복잡해진다. 생성자를 호출하는 부분도 복잡해진다
지역변수(매개변수 포함):
지역 변수(매개변수 포함): 지역 변수는 스택 영역에 있는 스택 프레임 안에 보관된다. 메서드가 종료되면 스택 프레임도 제거 되는데 이때 해당 스택 프레임에 포함된 지역 변수도 함께 제거된다. 따라서 지역 변수는 생존 주기가짧다
인스턴스 변수 : 인스턴스에 있는 멤버 변수를 인스턴스 변수라 한다. 인스턴스 변수는 힙 영역을 사용한다. 힙 영
역은 GC(가비지 컬렉션)가 발생하기 전까지는 생존하기 때문에 보통 지역 변수보다 생존 주기가 길다
클래스 변수: 클래스 변수는 메서드 영역의 static 영역에 보관되는 변수이다. 메서드 영역은 프로그램 전체에서
사용하는 공용 공간이다. 클래스 변수는 해당 클래스가 JVM에 로딩 되는 순간 생성된다. 그리고 JVM이 종료될
때 까지 생명주기가 어어진다. 따라서 가장 긴 생명주기를 가진다.
"정적"이라는 용어는 변하지 않는, 고정된, 또는 실행 시간 동안 변경되지 않는 것을 의미
인스턴스를 통한 정적변수 접근 / 보통근대 이렇게는 사용안햇는데..
권장하지 않음
왜냐? count라는게 인스턴스변수인가, 멤버변수인가 헷갈릴수 있음
인스턴스 메서드를 사용하는 예제
앞서 개발한 deco() 메서드를 호출하기 위해서는 DecoUtil1 의 인스턴스를 먼저 생성해야 한다. 그런데 deco()
라는 기능은 멤버 변수도 없고, 단순히 기능만 제공할 뿐이다.
인스턴스가 필요한 이유는 멤버 변수(인스턴스 변수)등을
사용하는 목적이 큰데, 이 메서드는 사용하는 인스턴스 변수도 없고 단순히 기능만 제공한다
중요 !!!!! 객체 생성의 의미가 크지가 않다..
정적 메서드로 기능 제공 예제
static 이 붙은 정적 메서드는 객체 생성 없이 클래스명 + . (dot) + 메서드 명으로 바로 호출할 수 있다.
정적 메서드 덕분에 불필요한 객체 생성 없이 편리하게 메서드를 사용했다
클래스 메서드
메서드 앞에도 static 을 붙일 수 있다. 이것을 정적 메서드 또는 클래스 메서드라 한다. 정적 메서드라는 용어는
static 이 정적이라는 뜻이기 때문이고, 클래스 메서드라는 용어는 인스턴스 생성 없이 마치 클래스에 있는 메서드를
바로 호출하는 것 처럼 느껴지기 때문이다.
인스턴스 메서드 static 이 붙지 않은 메서드는 인스턴스를 생성해야 호출할 수 있다. 이것을 인스턴스 메서드라 한다
정적 메서드 활용
![]ㄴ(https://velog.velcdn.com/images/superkkj/post/2df06055-2e5d-4602-ab0a-c045b060f28b/image.png)
각 선언에따른 그림
메모리 낭비(중복) 은 좋지않음 -> static으로 해결
static final -> 붙여서 해결 공유하면서 불변의 값
중복 메모리 문제 해결
기본형은 10 , 20
참조형은 참조값
final은 값을 변경할수 없기에 기본형은 값 변경 X
참조형은 참조값 변경 x
두둥 ..!
객체지향 프로그래밍의 핵심 요소 중 하나
기존 클래스의 필드와 메서드를 새로운 클래스에서 재사용 하게함
이름 그대로 부모 클래스의 속성과 기능을 그대로 물여 받음
비행기와 자동차를 상속받아 하늘을 나는 자동차를 만든다?
그런대 AirplaneCar 입장에서 move()를 호출할때 어떤 move() 사용할지 애매함
이것이 다이아몬드 문제...
이래서 다중상속을 사용하면 계층구조가 매우 복잡해 질수 있다
그러므로 자바는 다중 클래스 상속 허용 x 대신 인터페이스로 해결가능
부모가 또다른 부모를 가지는것 은 괜찬음
위코드에서 상속받은 코드
처음 보는 메모리구조인대 신기함.
상속 관계를 사용하면 부모 클래스를 포함해서 생성
인스턴스는 하나같지만 내부에서는 부모와 자식이 모두 생성되고 공간도 구분 됨.
부모 메서드를 이용하게 됨
이 애노테이션 기능은? 부모의 기능일 이용하게다는 명시적 의미
- 이름 그대로 오버라이딩한 메서드 위에 이 애노테이션을 붙여야 한다.
컴파일러는 이 애노테이션을 보고 메서드가 정확히 오버라이드 되었는지 확인한다.- 오버라이딩 조건을 만족시키지 않으면 컴파일 에러를 발생시킨다.
따라서 실수로 오버라이딩을 못하는 경우를 방지해준다.- 예를 들어서 이 경우에 만약 부모에 move() 메서드가 없다면 컴파일 오류가 발생한다.
참고로 이 기능은 필수는 아니지만 코드의 명확성을 위해 붙여주는 것이 좋다.
- 메서드 오버로딩: 메서드 이름이 같고 매개변수(파라미터)가 다른 메서드를 여러개 정의하는 것을 메서드 오버딩(Overloading)이라 한다.
- 오버로딩은 번역하면 과적인데, 과하게 물건을 담았다는 뜻이다.
- 따라서 같은 이름 의 메서드를 여러개 정의했다고 이해하면 된다.
메서드 오버라이딩: 메서드 오버라이딩은 하위 클래스에서 상위 클래스의 메서드를 재정의하는 과정을 의미한다.
1. 따라서 상속 관계에서 사용한다.
2. 부모의 기능을 자식이 다시 정의하는 것이다. 오버라이딩을 단순히 해석하면 무
언가를 넘어서 타는 것을 말한다.
3. 자식의 새로운 기능이 부모의 기존 기능을 넘어 타서 기존 기능을 새로운 기능으
로 덮어버린다고 이해하면 된다.
4. 오버라이딩을 우리말로 번역하면 무언가를 다시 정의한다고 해서 재정의라 한다.
5. 상속 관계에서는 기존 기능을 다시 정의한다고 이해하면 된다.
6. 실무에서는 메서드 오버라이딩, 메서드 재정의 둘다 사용한다.
상속 관계를 사용하면서 자식클래스의 생성자에서 부모클래스의 생성자 바로 호출해야됨(규칙)
객체지향 캡슐화 , 상속 , 다형성
다형성 이해는 어렵지만 이해가 필수
다형성은 말그대로 다양한 형태 / 여러 형태를 뜻함
프래그래밍에서 다형성은 한 객체가 여러 타입의 객체로 취급될 수 있는 능력을 뜻함
보통 하나의 객체는 하나의 타입으로 고정 되어있지만
다형성을 사용하면 하나의 객체가 다른 타입으로 사용가능!
지금까지 학습한 내용은 같은 타입에 참조를 대입 보통은 한가지 형태만 참조가능
다형적 참조의 핵심은 부모는 자식을 품을 수 있따는것
Child child = (Child) poly
(타입)처럼 괄호와 그 사이에 타입지정시 참조 대상을 특정 타입으로 변환 가능
업캐스팅 경우 문제발생 x 객체를 생성하면 해당 타입의 상위 부모타입이 함께 생성되기 때문
반면 다운캐스팅은 인스턴스에 존재하지않는 하위 타입으로 캐스팅 문제 발생
부모타입은 모두생성되지만 자식 타입은 생성되지 않아서
다형성에서 참조형 변수는 이름 그대로 다양한 자식 참조가능
하지만 어떤 자식을 참조 하는 알수있는 방법을 아는 방법을 알아보자
인스턴스가 child면 밑에 로직 실행해줘!
어떤 인스턴스를 참조하느냐 구분해준다.
오른쪽 대상의 자식 타입을 왼쪽에서 참조하는 경우 true
대입이 가능하면 true 못하면 false
x 자로 대입이 가능하면 true!
x 자 X자가 중요하다
실제 인스턴스가 뭔지 확인하고
그 인스턴스에 따라서 확인해보고 다운캐스팅을 내려서하면 안전하니까
오버라이딩 된 메서드는 항상 우선권을 가진다는것 ! 중요 !!
이름도 기존 기능을 덮어 새로운 기능을 재정의한 다는 뜻의 오버라이딩이다.
다형적 참조: 하나의 변수 타입으로 다양한 자식 인스턴스를 참조할 수 있는 기능
메서드 오버라이딩: 기존 기능을 하위 타입에서 새로운 기능으로 재정의
![]
계속해서 개선
새로운 동물이 추가되도 soundAnimal 메서드는 코드 변경없이 유지 가능..
Aninamal 이라는 추상저긴 부모를 참조하기 때문 .
변하는 부분이 최소화. 하는 것이 잘 작성된 코드.
Animal animal = new Animal()
개 , 고양이, 소가 실제 존재하는것 당연함
동물이라는 추상적인 개념이 실제로 존재하는건 이상함.
이 클래스는 다형성을 위해 필요한거지 직접 인스턴스를 생성해서 사용할 일 없음
하지만 Animal도 클래스기 때문에 인스턴스 생성하고 사용하는데 제약 없음
누군가 실수로 Anamal 사용해서 인스턴스 생성할수 있지만
제대로된 기능을 수행하지 않을듯.
동물(Animal) 과 같이 부모 클래스를 제공하지만
실제 생성되면 안되는 클래스를 추상 클래스라 함
말그대로 추상적인 개념을 제공하는 클래스 (인스턴스 존재 X)
상속을 목적으로 사용되고 부모클래스 역할 담당
abstact class AbstractAnimal
부모 클래스를 상속받는 자식 클래스가 반드시 오버라이딩 해야 하는 메서드를 부모 클래스에 정의 가능. 이것을 추상 메서드라 함
추상 클래스 는 말그대로 추상적인 개념 제공 메서드, 따라서 실체가 존재하지 않아 메서드 바디가 없다
public abstract void sound();
추상 메서드는 상속받은 자식 클래스 반드시 오버라이딩해야 함.
그렇지 않으면 컴파일 오류가 발생한다.
추상 메서드는 자식 클래스가 반드시 오버라이딩 해야 하기 때문에 메서드 바디 부분이 없다. 바디 부분을
만들면 컴파일 오류가 발생한다.
오버라이딩 하지 않으면 자식도 추상 클래스가 되어야 한다.
추상 메서드는 기존 메서드와 완전히 같다. 다만 메서드 바디가 없고, 자식 클래스가 해당 메서드를 반드시 오버라이딩 해야 한다는 제약이 추가된 것이다.
순수 추상 클래스: 모든 메서드가 추상 메서드인 추상 클래스
순수 추상 클래스는 다음과 같은 특징을 가진다.
인스턴스를 생성할 수 없다.
상속시 자식은 모든 메서드를 오버라이딩 해야 한다.
주로 다형성을 위해 사용된다
상속시 자식은 모든 메서드를 오버라이딩ㅎ해야 함
특징은 상속 받은 클래스 입장에서 보면 부모의 모든 메서드를 구현해야함
이런 특징은 순수 추상클래스는 마치 어떤 규격!을 지켜서 구현해야 하는 것 처럼 느낌
인터페이스와 비슷한대?
순수 추상클래스의 개념은 자바에서 더 편리하게 사용할수 있또록 인터페이스 라는 개념을 제공
자바에선 순수 추상클래스라는 이름이없다 인터페이스가 있기 때문
부모 클래스 기능을 자식 클래스가 상속 받을땐 상속이라 표현
부모 인터페이스의 기능을 자식이 상속받을때는 구현이라 함
왜?
상속은 이름 그대로 부모의 기능을 물려받는게 목적(오버라이드안된 메서드? 공통메서드?)
하지만 인터페이스는 모든 메서드가 추상 메서드.
따라서 구현한다고 표현.
인터페이스는 메서드 이름만 있는 설계도 / 이 설계도가 어떻게 동작하는지 하위클래스에서 모두구현해야함. 그래서 구현이라함
상속 구현은 사람마다 표현하는 단어만 다를 뿐이지 자바 입자ㅏㅇ에선 똑같다 일반 상속 구조와 동일하게 작동함
인터페이스를 만드는 이유?
다중 구현
인터페이스는 완전한 약속 완전히 구현해야되
추상클래스는 일부는 구현이 되어있어도 괜찮고 일부코드는 구현해야됨
불안전함.
추상클래스는 내가 기능을 넣어도 되니까 기능을 넣을까말까
인터페이스는 이런관점에서 다막아버린다.
객체지향 프로그래밍
K3 타다 테슬라 모델3로 ?
바로 운전 가능
운전자라는 역할 입장에서 보면 자동차를 바꿔도 영향을 안줌
자동차라는 역할과 구현으로 분리된 이유?
내가 운전자라는 역할 입장에서 자동차가 바뀌더라도
운전자의 역할은 바뀌지않음
무슨말? 자동차의 역할을 부여한것은 운전자인 나를 위해서
자동차의 내부구조 다 알필요 있어?
차를 바꾼다해서 세세하게 알필요없다
엑셀 밟으면가고 브레이크 밟으면 선다.
이런식으로 역할과 구현을 구분해놓으면 무한대로 자동차를 늘릴 수 있음
클라이언트인 운전자 역할에 영향을 안미치고.
왜 ? 역할과 구현으로 세상을 구분
비슷한 예제
운전자 역할 로미오 줄리엣 역할 입장에선 참좋다.
클라이언트는 전혀 변경되지 않지만 서버는 변경가능
하지만 역할인 인터페이스가 변하면 다 영향을 미친다..
차가 비행기로 바뀌면..
앞선 코드 예제에서 (생략했지만)
우리는 new 카를 추가해도
driver에 코드를 손댈 필요가 없다