상속은 기존의 클래스를 재활용하여 새로운 클래스를 작성하는 자바의 문법 요소이다.
상위 클래스 - 하위 클래스는 서로 상속 관계에 있다고 하며, 하위 클래스는 상위 클래스가 갖고 있는 모든 멤버를 상속한다.
상속을 통해 클래스를 작성하면 코드를 재사용하여 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있어 코드의 중복을 제거할 수 있다.
상속은 다형적(하나의 객체가 여러 모양으로 표현될 수 있다는 것) 표현이 가능하다는 장점이 있다.
-> ex) '나는 사람이다.' 그와 동시에 '나는 학생이다.'
extends
키워드를 사용하며, 클래스명 다음에 extends
상위 클래스명을 사용하여 정의한다.class Person {
String name;
int age;
void learn(){
System.out.println("공부를 합니다.");
};
void walk(){
System.out.println("걷습니다.");
};
void eat(){
System.out.println("밥을 먹습니다.");
};
}
class Programmer extends Person { // Person 클래스로부터 상속. extends 키워드 사용
String companyName;
void coding(){
System.out.println("코딩을 합니다.");
};
}
포함(composite)은 상속처럼 클래스를 재사용할 수 있는 방법으로, 클래스의 멤버로 다른 클래스 타입의 참조변수를 선언하는 것을 의미한다.
상속과 포함관계는 클래스 간의 관계가 ~은 ~이다(IS-A) [상속]
관계인지 ~은 ~을 가지고 있다(HAS-A) [포함]
관계인지 문장을 만들어 생각해보는 것이다.
메서드 오버라이딩(Method Overriding)은 상위 클래스로부터 상속받은 메서드와 동일한 이름의 메서드를 재정의하는 것이다.
성립조건
Vehicle[] vehicles = new Vehicle[] { new Bike(), new Car(), new MotorBike()};
for (Vehicle vehicle : vehicles) {
vehicle.run();
super
키워드는 상위 클래스의 객체, super()
는 상위 클래스의 생성자를 호출하는 것을 의미하며, 공통적으로 모두 상위 클래스의 존재를 상정하며 상속 관계를 전제한다.
두 개의 같은 이름의 변수를 구분하기 위한 방법이 바로 super
키워드다. super
키워드를 사용하면 부모의 객체의 멤버 값을 참고한다.
super()
메서드 또한 this()
와 마찬가지로 생성자 안에서만 사용가능하고, 반드시 첫 줄에 와야한다. 모든 생성자의 첫 줄에는 반드시 this()
또는 super()
가 선언되어야 한다.
만약
super()
가 없는 경우에는 컴파일러가 생성자의 첫 줄에 자동으로super()
를 삽입한다. 상위클래스에 기본생성자가 없으면 에러가 발생하게 된다.
Object
클래스는 자바의 클래스 상속계층도에서 최상위에 위치한 상위클래스다. 따라서 자바의 모든 클래스는 Object
클래스로부터 확장된다.class ParentEx { // 컴파일러가 "extends Object" 자동 추가
}
class ChildEx extends ParentEx {
}
-> ParentEx 클래스를 상속받아 ChildEx 클래스를 만들었을 때 상위클래스 ParentEx는 아무것도 상속하고 있지 않기에 컴파일러는 extends Object를 삽입한다.
메서드명 | 반환타입 | 주요내용 |
---|---|---|
toString() | String | 객체 정보를 문자열로 출력 |
equals(ObjectObj) | boolean | 등가 비교 연산(==)과 동일하게 스택 메모리값을 비교 |
hashCode() | int | 객체의 위치정보 관련. Hashtable 또는 HashMap 에서 동일 객체여부 판단 |
wait() | void | 현재 쓰레드 일시정지 |
notify() | void | 일시정지 중인 쓰레드 재동작 |
캡슐화란 특정 객체 안에 관련된 속성과 기능을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호하는 것이다.
캡슐화를 하는 이유로는, 데이터 보호의 목적과 내부적으로만 사용되는 데이터에 대한 불필요한 외부 노출을 방지하기 위함이다.
외부로부터 객체의 속성과 기능이 함부로 변경되지 못하게 막고, 데이터가 변경되더라도 다른 객체에 영향을 주지 않기에 독립성을 확보할 수 있고 유지보수와 코드 확장 시에도 오류의 범위를 최소화할 수 있어서 효과적으로 코드를 유지보수하기에 용이하다.
패키지(package)란 특정한 목적을 공유하는 클래스와 인터페이스의 묶음을 의미한다.
자바에서 패키지는 물리적인 하나의 디렉토리(directory)이고, 하나의 패키지에 속한 클래스나 인터페이스 파일은 모두 해당 패키지에 속해있다.
이 디렉토리는 하나의 계층구조를 가지고 있는데, 계층 구조 간 구분은 점(.)
으로 표현된다.
패키지가 있는 경우 소스 코드의 첫 번째 줄에 반드시 package 패키지명;
이 표시되어야 하고, 만약 패키지 선언이 없으면 이름없는 패키지에 속하게 된다.
패키지로 클래스를 묶는 것의 장점은 클래스의 충돌을 방지해주는 기능으로 같은 이름의 클래스를 가지고 있더라도 각각 다른 패키지에 소속되어 있다면 이름으로 인한 충돌이 발생하지 않는다.
import문
은 다른 패키지 내의 클래스를 사용하기 위해 사용하며, 일반적으로 패키지 구문과 클래스문 사이에 작성한다.package practicepack.test2; // import문을 사용하는 경우
import practicepack.test.ExampleImp // import문 작성
<import 패키지명.클래스명; 또는 import 패키지명.*;>
public class PackageImp {
public static void main(String[] args) {
ExampleImp x = new ExampleImp(); // 이제 패키지명을 생략 가능
}
}
import문
을 여러번 사용하기보다는 import 패키지명.*
으로 작성하면 해당 패키지의 모든 클래스를 패키지명 없이 사용 가능하다.접근 제어자 | 기타 제어자 |
---|---|
public, protected, (default), private | static, final, abstract, native, transient, synchronized 등 |
하나의 대상에 대해서 여러 제어자를 사용할 수 있지만, 각 대상에 대해서 접근 제어자는 단 한번만 사용할 수 있다.
접근 제어자를 사용하면 클래스 외부로의 불필요한 데이터 노출을 방지(data hiding)할 수 있고, 외부로부터 데이터가 임의로 변경되지 않도록 막을 수 있다.
접근 제어자 | 접근 제한 범위 |
---|---|
private | 동일 클래스에서만 접근 가능 |
default | 동일 패키지 내에서만 접근 가능 |
protected | 동일 패키지 + 다른 패키지의 하위 클래스에서 접근 가능 |
public | 접근 제한 없음 |
public(접근 제한 없음) > protected(동일 패키지 + 하위클래스) > default(동일 패키지) > private(동일 클래스)
default
가 된다.setter
메서드는 외부에서 메서드에 접근하여 조건에 맞을 경우 데이터 값을 변경 가능하게 해주고 일반적으로 메서드명에 set-
을 붙여서 정의한다.
getter
메서드는 이렇게 설정한 변수 값을 읽어오는 데 사용하는 메서드이며, get-
을 메서드명 앞에 붙여서 사용한다.
setter
와 getter
메서드를 활용하면 데이터를 효과적으로 보호하면서도 의도하는 값으로 값을 변경하여 캡슐화를 보다 효과적으로 달성할 수 있다.
public class GetterSetterTest {
public static void main(String[] args) {
Worker w = new Worker ();
w.setName("김코딩");
w.setAge(30);
w.setId(5);
String name = w.getName();
System.out.println("근로자의 이름은 " + name);
int age= w.getAge();
System.out.println("근로자의 나이는 " + age);
int id = w.getId();
System.out.println("근로자의 ID는 " + id);
}
}
class Worker {
private String name; // 변수의 은닉화. 외부로부터 접근 불가
private int age;
private int id;
public String getName() { // 멤버변수의 값
return name;
}
public void setName(String name) { // 멤버변수의 값 변경
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age < 1 ) return;
this.age = age;
}
public int getId() {
return id;
}
public void setId (int id) {
this.id = id;
}
}