기존의 클래스로 새로운 클래스를 작성하는 것(코드의 재사용)
두 클래스를 부모와 자식으로 관계를 맺어주는 것
class Parent() {} // 부모 관계
class Child extends Parent {} // 자식 관계
자손은 조상(부모의 부모)의 모든 멤버를 상속받는다.(생성자, 초기화블럭 제외)
자손의 멤버 개수는 조상보다 적을 수 없다.(같거나 많다)
자손의 변경은 조상에 영향을 미치지 않는다.
class Parent {
	int age;
}
class Child extends Parent {
	void play() {
    	System.out.println("놀자~");
    }
}

class Point {
	int x;
    int y;
}
1. class Point3D extends Point{      2. class Point3D {
	   int z;								int x;
}											int y;
											int z;
                                        }
Point3D p = new Point3D();

클래스의 멤버로 참조변수를 선언하는 것
class Point {
	int x;
    int y;
}
1. class Circle {        		  2. class Circle {
	 Point p = new Point();          	int x;
     int r; 							int y;
}   									int r;
									 }
Circle c = new Circle();
작은 단위의 클래스를 만들고, 이들을 조합해서 클래스를 만든다.
상속 관계 : ~은 ~이다(is-a)
포함 관계 : ~은 ~을 가지고 있다(has-a)
Java는 단일 상속(하나의 부모만 허용)만을 허용한다.
class Tv {
	boolean power;
    int channel;
    
    void power() { power = !power; }
    void channelUp() { ++channel; }
    void channelDown() { --channel; }
}
class DVD {
	boolean power;
    
    void power() { power = !power; }
    void play() {/*내용 생략*/}
    void stop() {/*내용 생략*/}
    void rew() {/*내용 생략*/}
    void ff() {/*내용 생략*/}
}
class TvDVD extends Tv {
	DVD dvd = new DVD();
    
    void play() {
    	dvd.play();
    }
    void stop() {
    	dvd.stop();
    }
    void rew() {
    	dvd.rew();
    }
    void ff() {
    	dvd.ff();
    }
부모가 없는 클래스는 자동적으로 Object 클래스를 상속받게 된다.
모든 클래스는 Object 클래스에 정의된 11개의 메서드를 상속받는다.
Circle c = new Circle();
System.out.println(c.toString());
System.out.println(c); // c.toString() 과 c 는 같은 값을 출력한다.
상속 받는 조상의 메서드를 자신에 맞게 변경하는 것
class Point {
	int x;
    int y;
    
    String getLocation() {
    	return "x= " +x+", y= "+y;
    }
}
class Point3D extends Point {
	int z;
    
    String getLocation() { // 오버라이딩, 선언부는 변경 불가
    	return "x= " +x+", y= "+y+", z= "+z; // 내용(구현부)만 변경 가능
    }
}
1. 선언부(반환타입, 메서드 이름, 매개변수 목록)가 조상 클래스의 메서드와 일치해야 한다.
2. 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
3. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
오버로딩(Overloading) : 기존에 없는 새로운 메서드(이름이 같은)를 정의하는 것(new)
오버라이딩(Overriding) : 상속 받은 메서드의 내용을 변경하는 것(modify)
class Parent {
	void parentMethod() {}
}
class Child extends Parent {
	void parentMethod() {}      // 오버라이딩
    void parentMethod(int i) {} // 오버로딩
    
    void childMethod() {}      // 메서드 정의
    void childMethod(int i) {} // 오버로딩
    void childMethod() {}      // 중복정의, 에러
    
}
객체 자신을 가리키는 참조변수, 인스턴스 메서드(생성자)내에만 존재
조상의 멤버를 자신의 멤버와 구별할 때 사용
class Ex7_2 {
	public static void main(String[] args) {
		Child c = new Child();
		c.method();
	}
}
class Parent { int x=10; } // super.x
class Child extends Parent {
	int x=20; // this.x
	void method() {
		System.out.println("x=" + x);
		System.out.println("this.x=" + this.x);
		System.out.println("super.x="+ super.x);
	}
}
결과
x=20
this.x=20
super.x=10
class Parent { int x=10; } : 조상의 멤버 x = super.x조상의 생성자를 호출할 때 사용
조상의 멤버는 조상의 생성자를 호출해서 초기화
class Point {
	int x, y;
    
    Point(int x, int y) {
    	this.x = x;
        this.y = y;
    }
}
class Point3D extends Point {
	int z;
    
    Point3D(int x, int y, int z) {
    	super(x, y); // 조상클래스의 생성자 Point(int x, int y)를 호출
        this.z = z;
    }
}
class Point {
	int x, y;
    
    Point(int x, int y) { this.x = x; this.y = y; }
}
class Point3D extends Point {
	int z;
    
    Point3D(int x, int y, int z) { this.x = x; this.y = y; this.z = z; }
}
public class PointTest {
	public static void main(String[] args) {
    	Point3D p3 = new Point3D(1, 2, 3);
    }
}    
Point3D p3 = new Point3D(1, 2, 3); 에서 에러 발생Point(int x, int y) { this.x = x; this.y = y; }
Point3D(int x, int y, int z) { this.x = x; this.y = y; this.z = z; }
생성자의 첫 줄에 생성자를 호출하지 않아서 자동으로 첫 줄에 super(); 추가
Point(int x, int y) {
	super(); // Object();
	this.x = x; 
	this.y = y;
}
Point3D(int x, int y, int z) {
	super(); // Point(); 호출
	this.x = x; 
	this.y = y;
    this.z = z;
}
해결 방법 2가지
class Point {
	int x, y;
    
    Point() {} // 기본 생성자 추가
    Point(int x, int y) { this.x = x; this.y = y; }
}
Point3D(int x, int y, int z) {
	super(x, y); // Point(int x, int y); 호출
    this.z = z;
}
클래스와 클래스의 멤버(멤버변수, 메서드)에 부가적인 의미 부여
하나의 대상에 여러 제어자를 같이 사용 가능(접근 제어자는 하나만)
접근 제어자를 제일 왼쪽에 쓰는게 좋다.
사용 대상 : 멤버변수, 메서드
class StaticTest {
	static int width = 200;  // 클래스 변수(cv)
    static int height = 100; // 클래스 변수(cv)
    
    static { // 클래스 초기화 블럭
    	// static 변수의 복잡한 초기화 수행
    }
    
    static int max(int a, int b) { // 클래스 메서드(static 메서드)
    	return a + b;
    }
}
사용 대상 : 클래스, 메서드, 멤버변수, 지역변수
final class FinalTest { // 조상이 될 수 없는 클래스
	final inx Max = 10; // 값을 변경할 수 없는 변수(상수)
    
    final void getMaxSize() { // 오버라이딩할 수 없는 메서드
    	final int LV = Max;
        return Max;
    }
}
사용 대상 : 클래스, 메서드
abstract class AbstractTest {
	abstract void move();
}
AbstractTest a = new AbstractTest(); // 에러
private : 같은 클래스 내에서만 접근 가능
(default) : 같은 패키지 내에서만 접근 가능(아무것도 쓰지 않는 것)
protected : 같은 패키지 + 다른 패키지의 자손 클래스에서 접근 가능
public : 접근 제한 x
접근 제어자를 사용하는 이유
-> 외부로부터 데이터를 보호하기 위해서(캡슐화)
public class Time {
	public int hour, minute, second; // 접근 제한 x
}
Time t = new Time();
t.hour = 25; // 멤버변수에 직접 접근	
class Time {
    private int hour, minute, second;
    public void setHour(int hour) { 
        if(isNotValidHour(hour)) return;
        this.hour = hour;
    }
    private boolean isNotValidHour(int hour) {
        return hour < 0 || hour > 23;
    }
    public int getHour() { return hour; }
}
public class TimeTest {
    public static void main(String[] args) {
        Time t = new Time();
        t.setHour(21);
        System.out.println(t.getHour());
        t.setHour(210);
        System.out.println(t.getHour());
    }
}
private int hour, minute, second;
외부에서 접근하지 못하도록 private로 지정
public void setHour(int hour) { if(isNotValidHour(hour)) return; this.hour = hour; }
- 메서드를 public 으로 설정하여 간접 접근 허용
 - 매개변수 hour의 범위가 유효한지 확인하기 위한 메서드 생성
 
private boolean isNotValidHour(int hour) { return hour < 0 || hour > 23; }접근 제어자의 범위는 가능한 최소한으로 설정(private)
-> 나중에 코드를 수정하고 확인할 때 접근 제어자의 범위만 확인하면 되기 때문에 시간을 절약할 수 있다.