상속
- 기존의 클래스로 새로운 클래스를 작성하는 것
- 두 클래스를 부모와 자식으로 관계를 맺어주는 것
상속의 특징
- 재사용성을 높이고 코드의 중복을 제거하여 프로그램의 생산성과 유지보수에 크게 기여한다
class Parent {}
class Child extends Parent {
// 자식 상속 부모
}
포함(Composite)
- 작은 단위의 클래스를 만들고, 이 들을 조합해서 클래스를 만든다.
class MyPoint{
int x;
int y;
}
class Circle { //포함
MyPoint p = new MyPoint();
int r;
}
public class InheritanceTest {
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= " + c.p.x);
System.out.println("c.p.y= " + c.p.y);
System.out.println("c.r= " + c.r);
}
}
단일 상속
- 하나의 부모로부터 상속받을수 있게 하는 것을 단일 상속 이라고 한다.
Object클래스 - 모든 클래스의 조상
부모가 없는 클래스는 자동적으로 Object클래스를 상속받게 된다.
자바의 모든 클래스들은 Object클래스의 멤버들을 상속 받기 때문에 Object클래스에 정의된 멤버들을 사용할 수 있다.
- ex) toString()이나 equals(Object o) 등
참조변수 super
- 객체 자신을 가리키는 참조변수. 인스턴스 메서드(생성자)내에만 존재
- 조상의 멤버를 자신의 멤버와 구별할 떄 사용
public class SuperTest {
public static void main(String[] args) {
Child c =new Child();
c.method();
}
}
class Parent{
int x = 10;
}
class Child extends Parent{
int x= 20;
void method() {
System.out.println("x= " + x);
System.out.println("this.x= " + this.x);
System.out.println("super.x= " + super.x);
}
}
super() - 조상의 생성자
- 조상의 생성자를 호출할 때 사용
- 조상의 멤버는 조상의 생성자를 호출해서 초기화
- static메서드에서는 this와 super을 사용할 수 없고 인스턴스 메서드에서만 사용가능하다.
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; //자신의 멤버를 초기화 } }
패키지(package)
- 서로 관련된 클래스의 묶음
- 클래스는 클래스 파일(.class), 패키지는 폴더. 하위 패키지는 하위 폴더
패키지의 선언
- 패키지는 소스파일의 첫 번째 문장으로 단 한번 선언
- 모든 클래스는 반드시 하나의 패키지에 속해야 한다.
- 패키지는 점(.)을 구분자로 하여 계층구조로 구성할 수 있다.
- 클래스명과 쉽게 구분하기 위해서 소문자로 하는것을 원칙으로한다.
- 패키지 선언이 없으면 이름 없는 패키지에 속하게 된다.(nunamed)
package com.codechobo.book; //패키지 선언
public class PackageTest{
public static void main(String[] args){
System.out.println("Hello, world!");
}
}
class PackageTest2 {}
import문
이클립스 단축키 : ctrl + shift + o
- 클래스를 사용할 때 패키지이름을 생략할 수있다.
- 컴파일에게 클래스가 속한 패키지를 알려준다.
- import문의 역할은 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공하는 것이다.
- import문은 프로그램의 성능에 전혀 영향을 미치지 않는다. import문을 많이 사용하면 컴파일 시간이 아주 조금 더 걸리는거 뿐이다
- java.lang패키지의 클래스는 import하지 않고도 사용할 수 있다.
import java.lang.*; //모든 클래스, 생략가능
class ImportTest2
{
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
→ 패키지명.* 을 이용해서 지정된 패키지에 속하는 모든 클래스를 패키지명 없이 사용가능하다
→ 하지만, import하는 패키지의 수가 많을 때는 어느 클래스가 어느 패키지에 속하는지 구별하기 어렵다는 단점이있다.
→ import문에서 클래스의 이름 대신 '*'을 사용하는 것이 하위 패키지의 클래스까지 포함하는 것은 아니라는 것이다.
Static import문
- static멤버를 사용할 때 클래스 이름을 생략할 수 있게 해준다.
import static java.lang.System.out;
import static java.lang.Math.*;
class Ex7_6{
public static void main(String[]args){
//System.out.println(Math.random());
out.println(random());
//System.out.println("Math.PI :"+Math.PI);
out.println("Math.PI :" + PI);
}
}
- System과 String 같은 java.lang패키지의 클래스들을 패키지명 없이 사용할 수 있었던 이유는 모든 소스파일에는 묵시적으로 다음과 같은 import문이 선언되어 있기 때문이다.
- java.lang패키지는 매우 빈번히 사용되는 중요한 클래스들이 속한 패키지이기 때문에 따로 import문으로 지정하지 않아도 되도록 한 것이다.
제어자(modifier)
- 클래스와 클래스의 멤버(멤버 변수,메서드)에 부가적인 의미 부여
- 접근 제어자 : public, protected, (default), private
- 그 외 : static, final, abstract, native, transient, synchronized, volatile, strictfp
- 단, 접근 제어자는 한 번에 네 가지 중 하나만 선택이 가능하다
- 하나의 대상에 여러 제어자를 같이 사용가능(접근 제어자는 하나만)
public class ModifierTest{
public static final int WIDTH = 200;
제어자
public static void main(Stirng[] args){
System.out.println("WiDTH=" + WIDTH);
}
}
제어자 조합
제어자를 조합해서 사용할 떄 주의해야 할 사항
- 메서드에 static과 abstract를 함께 사용할 수 없다
- static메서드는 몸통이 있는 메서드에만 사용할 수 있기 때문이다
- 클래스에 abstract와 final을 동시에 사용할 수 없다
- 클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미이고 abstract는 상속을 통해서 완성되어야 한다는 의미이므로 서로 모순되기 때문이다.
- abstract메서드의 접근 제어자가 private일 수 없다
- abstract메서드는 자손클래스에서 구현해주어야 하는데 접근 제어자가 private이면, 자손클래스에서 접근할 수 없기때문이다
- 메서드에 private과 final을 같이 사용할 필요는 없다
- 접근 제어자가 private인 메서드는 오버라이딩될 수 없기 때문이다. 이 둘중 하나만 사용해도 의미가 충분하다.
접근 제어자(access modifier)
접근 제어자는 멤버 또는 클래스에 사용되어, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할
class 앞에는 public, default을 붙일수 있는데 default는 class앞에 아무런 제어자도 없으면 자동으로 default로 인식한다
멤버 앞에는 public, protected, default, private 모두 사용이 가능하다
package pkg1;
public class MyParent{ //접근제어자가 public
private int prv; //같은 클래스
int dft; //같은 패키지
protected int prt; //같은 패키지 + 자손(다른패키지)
public int pub; //접근제한 없음
public void printMembers() {
System.out.println(prv); // OK
System.out.println(dft); // OK
System.out.println(prt); // OK
System.out.println(pub); // OK
}
}
class MyParentTest { //접근제어자가 (default)
public static void main(String[] args) {
MyParent p = new MyParent();
// System.out.println(p.prv); //에러. 다른 클래스에서 접근해서 에러
System.out.println(p.dft); // OK
System.out.println(p.prt); // OK
System.out.println(p.pub); // OK
}
}
package pkg2;
import pkg1.MyParent; // ctrl+shift+o
class MyChild extends MyParent{
public void printMembers() {
// System.out.println(prv); // 에러 클래스 에서만
// System.out.println(dft); // 에러 패키지 에서만
System.out.println(prt); // OK
System.out.println(pub); // OK
}
}
public class MyParentTest2 {
public static void main(String[] args) {
MyParent p = new MyParent();
// System.out.println(p.prv); //에러. 다른 클래스에서 접근해서 에러
// System.out.println(p.dft); //에러. 다른 패키지에서 접근해서 에러
// System.out.println(p.prt); //에러. 다른 패키지 + 자손(다른패키지)에서 접근해서
System.out.println(p.pub); // OK
}
}
총 정리
상속 : 상위클래스에 있는 메서드를 하위클래스에서 사용가능하게 해준다
단일 상속 : 단 하나의 상위클래스의 상속받아서 사용할 수있다
(상위 클래스가 상속받은 자식 클래스보다 매개변수가 더 많으면 안된다)
this: 인스턴스 변수를 가르킬때 사용한다
super : 상위클래스에있는 변수를 가르킬때 사용한다
포함 : 클래스멤버로 참조 변수를 선언하는것
오버라이딩: 부모클래스의 메서드와 이름이 같아야한다. 매개변수도 같아야한다. 반환타입이 같아야한다
패키지 : 서로관계된 클래스들의 묶음
Object는 가장 상위 클래스 이다
import문 : 컴파일에게 클래스가 속한 패키지를 알려준다
접근제어자 : public, default, protected, private 가 있는데
public : 어디서든 접근이 가능하다
default : 같은 패키지에서만 접근이 가능하다
protected : 같은 패키지 + 자식 클래스까지 접근이 가능하다
private : 같은 클래스에서만 접근이 가능하다