본문 바로가기

JAVA

7장_1

1. 상속

- extends 키워드 사용

- 기존의 클래스로 새로운 클래스를 작성하는 것 = 두 클래스를 부모와 자식으로 관계를 맺어주는 것

- 자손은 조상의 모든 멤버를 상속받는다. (생성자, 초기화 블록 제외)

- 자손의 멤버 개수는 조상보다 적을 수 없다. (최소 같거나 많음)

- 자손의 변경은 조상에 영향을 미치지 않는다. <-> 부모의 변경은 자손에 영향을 미친다. (깊은 관계가 있음)

- 자바는 단일 상속만 허용한다. -> 두 개 이상의 클래스에서 같이 메서드가 존재할 경우 충돌의 문제가 있다.
                                               -> 이를 해결하기 위해 인터페이스 사용

 

🔎 상속과 포함 예제

// 상속
public class Main {

	public static void main(String[] args) {
		Circle c = new Circle();
		c.x = 1;
		c.y = 2;
		c.r = 3;
        
		System.out.println(c.x);
		System.out.println(c.y);
		System.out.println(c.r);
	}

}

class Point {
	int x;
	int y;
}

class Circle extends Point {
	int r;
}

 

// 포함
public class Main {

	public static void main(String[] args) {
		Circle c = new Circle();
		c.p.x = 1;
		c.p.y = 2;
		c.r = 3;
        
		System.out.println(c.p.x);
		System.out.println(c.p.y);
		System.out.println(c.r);
	}

}

class Point {
	int x;
	int y;
}

class Circle {
	Point p = new Point();
	int r;
}

 

 

2. Object 클래스

모든 클래스의 조상 - 모든 클래스는 Object 클래스를 상속받음

부모가 없는 클래스는 자동적으로 Object 클래스를 상속 받음 (컴파일러가 자동으로 추가해줌)

ex) 어떤 걸 상속받느냐? Object가 가진 11개의 메서드. toString(), equals(), hashCode()...

 

Circle c = new Circle();

// toString()은 객체의 주소를 반환하며, 둘 다 같은 값이 나오므로 참조 변수만 쓰자.
System.out.println(c.toString());
System.out.println(c); // 이걸 사용하자

 

 

3. 오버라이딩

상속받은 조상의 메서드를 자신에 맞게 변경하는 것

선언부는 바꿀 수 없고, 구현부({ })만 변경 가능

 

조건

- 선언부가 조상 클래스의 메서드와 일치해야 한다. (=구현부만 바꿔라)

- 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.

- 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.

 

public class Main {

	public static void main(String[] args) {
		Circle c = new Circle();
		c.x = 1;
		c.y = 2;
		c.z = 3;
        
		System.out.println(c.getLocation()); // x: 1, y: 2, z: 3
	}

}

class Point {
	int x;
	int y;
    
	String getLocation() {
		return "x: " + x + ", y: " + y;
	}
}

class Circle extends Point{
	int z;
	
	String getLocation() { // 오버라이딩
		return "x: " + x + ", y: " + y+ ", z: " + z;
	}
}

 

 

cf) 오버로딩 : 이름이 같은 기존에 없는 새로운 메서드를 정의하는 것 (new) 

     오버라이딩 : 상속받은 메서드의 내용을 변경하는 것 (change, modify)

 

 

4. 참조변수 super / 조상의 생성자 super()

super

- 객체 자신을 가리키는 참조변수

- 인스턴스 메서드, 생성자 내에만 존재

- 조상 멤버와 자신의 멤버를 구별할 때 사용


cf) 참조변수 this는 인스턴스변수와 지역변수를 구분할 때 사용했지!

 

super -> 조상 멤버와 자식 멤버 구별할 때, 조상 멤버에 쓰임
this -> 인스턴스 변수와 지역 변수 구별할 때, 인스턴스 변수에 쓰임

 

public class Main {
	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); // 20
		System.out.println("this.x = " + this.x); // 20
		System.out.println("super.x = " + super.x); // 10
	}
}

 

super()

조상의 생성자를 호출할 때 사용

조상의 생성자는 상속되지 않기 때문에! this() 못쓰고, super()를 써야 됨!!

 

public class Main {
	public static void main(String[] args) {
		Point3D p = new Point3D(1, 2, 3);
		System.out.println(p.toString()); // x= 1, y= 2, z= 3
	}
}

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); // 조상님 변수는 조상님이 초기화하세요~
		this.z = z;
	}
	
	@Override
	public String toString() {
		return "x= " + x + ", y= " + y + ", z= " + z;
	}
}

 

5. 패키지와 클래스 패스

패키지

서로 관련된 클래스의 묶음

같은 이름의 클래스 일지라도 서로 다른 패키지에 존재하는 것이 가능.

왜? 사실 클래스의 실제 이름은 패키지명을 포함한 것이기 때문에

 

클래스 패스

자바가 컴퓨터의 어느 곳에서나 사용 가능하게 하려고 미리 경로를 지정해주는 것

(그동안 이클립스 처음 깔 때, 환경변수를 지정해줬던 이유가 바로 이것!!)

 

'환경변수-새로 만들기'에서 패키지의 루트 디렉토리(C: ~~ /bin)를 classpath에 포함시키면

콘솔 창에서 패키지의 루트 디렉토리인 bin 폴더로 cd하고 java com.test.ex.Main 하지 않아도

바로 java com.test.ex.Main 로 실행 가능하다.

bin까지 하는 이유? bin에 실행 파일이 있기 때문에!

 

 

6. import문

클래스를 사용할 때 패키지 이름을 생략할 수 있다.

 

// 원시적인 방법
java.util.Date today = new java.util.Date();

// import문 사용하기
import java.util.Date;
Date today = new Date();

 

컴파일러에게 클래스가 속한 패키지를 알려준다.

java.lang 패키지의 클래스는 import하지 않고도 사용할 수 있다.

(String, Object, System, Thread...)

 

static import문

static 멤버를 호출할 때 클래스 이름을 생략할 수 있다.

특정 클래스의 static 멤버를 자주 사용할 때 편리하다.

 

// 위에 static 클래스를 선언해두면
import static java.lang.System.out;
import static java.lang.Math.*;

class Main {
	public static void main(String[] args) {
        // 아래에서 클래스를 떼고 편하게 사용 가능하다.
        
        out.println(random());
        // System.out.println(Math.random());
        
        out.println(PI);
        // System.out.println(Math.PI);
    }
}

 

7. 제어자

클래스, 변수, 메서드의 선언부에 사용

하나의 대상에 여러 제어자를 같이 사용할 수 있지만, 접근 제어자는 하나만!

 

- 접근 제어자

클래스 : public, (default)

메서드, 변수 : public, protected, (default), private

 

private 같은 클래스
(default) 같은 패키지
protected 같은 패키지 + 다른 패키지의 자손 클래스
public 접근 제한 없음 / 상속이 가능하려면 public 클래스로!

 

- 제어자

static (클래스의, 공통적인)

멤버변수, 메서드, 초기화 블럭에 사용 가능

 

멤버변수 - 모든 인스턴스에 공통적으로 사용하는 변수 (따라서, 공통적으로 사용하는 변수에는 static을 붙여주자)
- 인스턴스를 생성하지 않고도 사용 가능 (new 하지 않고도 사용 가능)
- 클래스가 메모리에 로드될 때 생성
메서드 - 인스턴스를 생성하지 않고도 호출이 가능
- static 메서드 내에서는 인스턴스 멤버(메서드,변수) 직접 사용 불가
   (따라서, 인스턴스 멤버를 사용하지 않는 메서드에는 static을 붙여주자)

 

final (마지막의, 변경될 수 없는)

클래스, 메서드, 멤버변수, 지역변수에 사용 가능

 

클래스 - 변경될 수 없는 클래스, 확장될 수 없는 클래스 = 마지막 클래스 
- 따라서, final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다. (상속을 막을 때 사용)
메서드 - 변경될 수 없는 메서드
- 오버라이딩을 통해 재정의 될 수 없음
멤버변수, 지역번수 - 값을 변경할 수 없는 상수


abstract (추상의, 미완성의)

클래스, 메서드에 사용 가능

 

클래스 클래스 내에 추상 메서드가 있을 때
메서드 선언부만 있고 구현부가 없을 때


그 외

native, transient, synchronized, volatile, strictfp

 

 

8. 캡슐화와 접근 제어자

접근 제어자를 사용하는 이유

- 외부로부터 데이터를 보호하기 위해서

- 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서

 

캡슐화

- 변수에 private 제어자를 붙여 직접 접근을 막고, public 메서드를 통해 접근하도록 함 (get, set)

 

 

예를 들어, 시간을 표시하기 위한 클래스 Time이 있다.

hour(0~24), minute(0~59), second(0~59) 모두 정해진 범위가 있는데 막 가져다가 쓰면

30시 88분 72초와 같은 잘못된 값이 들어갈 수 있다.

이처럼 값을 보호해야 할 때, 접근 제어자를 활용해서 캡슐화를 해야 한다.

 

class Time {
	private int hour;
	private int minute;
	private int second;
	
	public int getHour() {
		return hour;
	}
	public void setHour(int hour) {
		if(hour < 0 || hour > 23) return; // 0~23 아니면 거절
		this.hour = hour; // 0~23 사이면 그 값을 내보내
	}
	
	public int getMinute() {
		return minute;
	}
	public void setMinute(int minute) {
		if(minute < 0 || minute > 59) return; // 0~59 아니면 거절
		this.minute = minute;
	}
	
	public int getSecond() {
		return second;
	}
	public void setSecond(int second) {
		if(second < 0 || second > 59) return; // 0~59 아니면 거절
		this.second = second;
	}
}


// Main 클래스
public class Main {

	public static void main(String[] args) {
		Time t = new Time();
		t.setHour(3);
		t.setMinute(15);
		t.setSecond(45);
		
		System.out.println(t.getHour()); // 3
		System.out.println(t.getMinute()); // 15
		System.out.println(t.getSecond()); // 45
	}

}

'JAVA' 카테고리의 다른 글

7장_3  (0) 2021.01.22
7장_2  (0) 2021.01.22
쓰레드  (0) 2021.01.20
다형성 / 동적 바인딩 / 인터페이스 / 추상클래스  (0) 2021.01.18
static은 언제 붙일까?  (0) 2021.01.14