클래스간의 관계 : 상속, 포함
상속 : A는 B이다 (is - a)
기존의 클래스로 새로운 클래스를 만드는것 (부모-자식)
class 자식 extends 부모{}
자식은 모든 멤버를 상속받는다(생성자,초기화블럭 제외)
포함 : A는 B를 가지고 있다(has - a), 대부분 포함으로 사용
클래스가 다른클래스의 객체를 생성한것
class MyPoint(){
int x;
int y;
}
class Circle(){
MyPoint p = new MyPoint();
int r;
}
public class Compositon(){
public static void main(String[] args){
Circle c = new Circle();
}
}
1. composition 스택에 처음 호출
2. composition 안에 참조변수 c 생성, null로 초기화
3. circle 스택에 호출
4. circle 안에 참조변수 p 생성, int r 생성, c에 circle주소 대입
5. p = null, r = 0으로 초기화
6. 외부공간에 x,y생성, 둘다 0으로 초기화
7. p에 x,y가 있는 주소 대입
단일상속
하나의 부모로부터만 상속 받을 수 있다
다중상속이 필요한 경우 비중이 높은 클래스만 상속하고 나머지는 포함으로 처리한다
Object클래스 - 모든 클래스의 조상
부모가 없는 경우는 자동으로 Object를 상속하게 컴파일러가 만들어준다
print(c) == print(c.toString())
오버라이딩
상속받은 조상의 메서드를 자신에 맞게 변경하는것
자기 클래스에서 내용(구현)만 변경, 선언은 변경불가
조건
1. 선언부 동일
2. 접근제어자를 부모보다 좁은 범위 불가
3. 예외는 조상보다 많이 선언 할 수 없다
오버로딩 vs 오버라이딩
오버로딩->
상속과 무관, 이름만 같은 새로운 메소드를 정의(매개변수 변경)
오버라이딩->
상속받은 메서드의 내용을 변경
class Parent(){
void parentMethod(){~a~}
}
class Child extends Parent{
void parentMethod(){~b~} ->오버라이딩
void parentMethod(int i){~c~} ->오버로딩
void childeMethod(){~} ->메서드 정의
void childeMethod(int i){~} ->오버로딩
}
참조변수 super
this와 유사, im(인스턴스 메서드)내에서만 존재
조상의 멤버와 자신의 멤버를 구별할 때 사용
조상의 멤버일때는 super
자신의 멤버일때는 this
자신의 멤버가 따로 없을때는 super와 this가 동일한 대상을 가리킨다
조상의 생성자 super()
조상의 생성자를 호출할때 사용, 조상의 생성자와 초기화 블럭은 상속할 수 없다
★ ★ ★ 생성자는 첫줄에 반드시 생성자를 호출해야 하는데 ★ ★ ★
그렇지 않으면 컴파일러가 생성자의 첫줄에 super()를 삽입한다->상속을 안해도 object를 항상 상속중이니까 가능
항상 클래스를 생성할때는 기본 생성자를 작성해서 이유모를 에러를 피하자!!
class Point{
int x,y;
//2.
//1번에서 super()를 사용했기 때문에 여기에 기본생성자가 있어야 하는데
//기본생성자가 Point class에 존재 하지 않는다 -> 에러 발생
//항상 클래스를 생성할때는 기본 생성자를 생성해놔야 이런 실수를 피할 수 있다
Point(int x,int y){
this.x = x;
this.y = y;
}
String getLocation(){
return "x :" + x + ", y:"+ y;
}
}
class Point3D extends Point{
int z;
Point3D(int x, int y, int z){
//1.
//생성자는 첫줄에 기본 다른 생성자를 바드시 호출 해야한다
//아무것도 없으니까
//super() 생성 되었을것->Point에서 확인해보자
this.x =x;
this.y =y;
this.z =z;
//3.
//만약
//super(x,y);
//this.z =z;
//이렇게 했으면 에러는 발생하지 않는다
}
String getLocation(){
return "x :" + x + ", y:" + y + ", z :" + z;
}
}
class PointTest{
public static void main(String args[]){
Point3D p3 = new Point3D(1,2,3);
}
}
패키지- 서로 관련된 클래스의 묶음
클래스는 클래스파일(*.class)
패키지는 폴더, 하위패키지는 하위 폴더
클래스의 원래 이름은 패키지를 포함한다 ex) java.lang.String.class
rt.jar는 클래스들을 압축한 파일
rt = runtime -> 실행중
jar = 클래스파일을 묶어 둔것, zip 이랑 같은 의미
rt.jar는 크기가 너무커서 1.9부터 사라졌다
패키지는 소스파일의 첫번째 문장으로 딱 한번 선언
같은 소스 파일의 클래스들은 위에서 선언한 패키지에 같이 속하게 된다
패키지 선언이 없으면 이름없는(default)패키지에 속하게 된다
패키지는 . 으로 상위 하위 구분
import
클래스를 사용할 때 패키지이름을 생략 할 수 있다 -> 컴파일러가 자동으로 찾는다
import java.util.Date;
class ImportTest{
Date today = new Date();
}
여기서 Date();를 만나면 자동으로 java.util패키지에 있는 Date()클래스를 사용한다
기본패키지에 있는 클래스는 import안해도 된다
서로다른 패키지에 같은 이름의 클래스가 있으면 패키지이름을 써줘야 한다
static import - > 클래스 이름을 생략 할 수 있게 해준다
import static java.lang.Math.*
System.out.println(.random());
이런식으로 클래스 안붙이고 사용가능
제어자 = 형용사? - > 클래스나 클래스 멤버(멤버 변수, 메소드)에 부가적인 의미
접근제어자 : public, protected, (default), private, 그외 등등 있음
접근제어자를 가장 먼저 쓰고, 접근제어자는 하나만 사용가능하다
static
멤버변수 -> cv
초기화 블럭-> 복잡한 초기화할때 static블럭으로 초기화 한다
클래스 메서드 앞에도 붙인다
final -> 어디에서든 사용가능
클래스에 붙으면 상속불가
변수 앞에 붙으면 상수화
메서드 앞에 붙으면 오버라이딩 (조상 메서드 변경)불가
abstract->추상
몸통이 없는 추상 메서드
추상 메서드를 포함한 클래스
추상 클래스는 인스턴스(객체)를 생성 할 수없다
추상 클래스를 상속받은 후 완전한 클래스(구상 클래스)를 만들고 객체를 생성한다
접근제어자
private : 같은 클래스
default : 같은 패키지
protected : 같은패키지 + 다른 패키지 자손
public : 제한x
클래스는 public or (default) 둘중 하나만 가능하다
소스파일에는 하나의 public만 가능한데 pulic 클래스 이름이랑 소스파일 이름이랑 동일해야 한다
캡슐화 8:25~
접근제어자를 사용하는 이유 = 외부로부터 데이터를 보호하기 위해서 ->> 캡슐화
직접 접근을 막고 메소드를 통해서 접근 시키기 위해서
접근제어자의 범위를 최대한 줄여야 테스트 할때 편하다
특히 하나의 클래스내에서 사용되는 메서드는 protected로 만들어두자
다형성
조상 타입 참조변수로 자손타입 객체를 다루는것
자손 타입 참조변수로 조상타입 객체는 다룰 수 없다 -> 멤버개수가 자손이 많거나 같다
Tv t = new Tv();
SmartTv s = new SmartTv();
//위는 나의 리모컨을 나의제품과 연결
Tv t = new SmartTv();
//Tv 리모컨 t를 SmartTv 제품과 연결
타입이 불일치 해도상관없다
조상타입 참조변수t 와 자손의 객체 SmartTv와 연결
참조변수의 형변환
사용할 수 있는 멤버의 갯수를 조절 하는것->리모컨을 변경 해주면서
조상-자손 간의 참조변수가 서로 형변환 가능하다
down일때는 (자손 타입)조상 참조변수 -> 이렇게 사용해야한다
다형성일때와 다르게 기능을 멤버를 못쓰는거 뿐이지 에러는 발생 안한다
class Car{
String car;
int door;
void Drive();
void Stop();
}
class Fire extends Car{
void water();
}
Fire f = new Fire();
Car c = new Car();
Car c = f; // 업스케일링
Fire f = (Fire)c; //다운스케일링
다운스켕일링은 사용가능한 멤버 개수를 늘리는것이기 때문에 위험하다
-> 명시해줘야 한다
중요한건 형변환 했다고 하더라도 실제 가리키는 객체가 가지는 멤버가 중요하다
컴파일 에러는 안나더라도 실행할때 포함하지 않는 멤버를 사용하면 에러가 난다
car에서는 water()가 없고 fire에만 water()가 있는데
Fire f = (Fire) c;
f.water() ->불가능 하다 왜? ->c가 가리키는건 Car이기때문에
f.dive()-> 이런건 가능
instanceof 연산자
참조변수의 형변환 가능여부 확인할때 사용, 가능하면 true반환
'JAVA > 자바의 정석' 카테고리의 다른 글
자바의 정석 CH07 객체지향2-2 (1) | 2024.01.27 |
---|---|
자바의정석CH6 객체지향-1 (0) | 2024.01.17 |
자바의 정석ch5 배열 (0) | 2024.01.16 |
자바의정석CH4 조건문과 반복문 (0) | 2024.01.16 |
자바의 정석 CH3 (0) | 2024.01.16 |