1. 상속
기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것
구현 방법 : 'extends' 이용
Ex) class Student extends School
여기서 Student와 School 클래스는 서로 상속 관계에 있으며,
상속을 받는 Student 클래스는 자손(자식) 클래스,
상속해주는 School 클래스는 조상(부모) 클래스라고 한다.
위의 예시에서 Student 클래스는 이미 상속을 한 번 받았는데, 만약 이 Student클래스를 상속받아
A라는 클래스가 생성된다면, A와 School은 간접적인 상속관계라고 할 수 있다.
부모 클래스를 상속받아 만든 자손 클래스는 변경사항이 생겨도 부모 클래스에 영향을 주지 않지만,
부모 클래스에서 변경이 생기면 자손 클래스는 영향을 받는다.
★ 상속 시 멤버만 상속되며, 생성자와 초기화 블럭은 상속되지 않는다.
★ 자식 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
★ 클래스 간의 관계에서 부모/자식 관계(상속관계)는 있지만, 형제 관계는 없다.
★ 자바에서의 상속은 단일 상속만 가능하다.
즉, 자손 클래스의 인스턴스를 생성한다면 조상 클래스의 멤버와 자손 클래스의 멤버가 합쳐진 하나의 인스턴스로 생성된다.
※ 포함관계
상속 이외에 클래스를 재사용하는 방법으로 클래스간에 포함관계를 만드는 것이다.
한 클래스의 멤버변수로 다른 클래스 다입의 참조변수를 선언함으로써 포함관계를 맺어줄 수 있다.
Ex) Circle와 Point라는 클래스가 있다고 하면
class Circle {
Point p = new Point( ); //포함 관계
int r;
}
# 예제1
class Shape{
String color = "black";
void draw(){
System.out.printf("[color=%s]%n", color);
}
}
class Point{
int x;
int y;
Point(int x, int y){
this.x = x;
this.y = y;
}
Point(){
this(0, 0);
}
String getXY(){
return "(" + x + "," + y + ")";
}
}
class Circle extends Shape{
Point center;
int r;
Circle(){
this(new Point(0, 0), 100);
}
Circle(Point center, int r){
this.center = center;
this.r = r;
}
void draw() {
System.out.printf("[center=(%d, %d), r=%d, color=%s]%n",
center.x, center.y, r, color);
}
}
class Triangle extends Shape{
Point[] p = new Point[3];
Triangle(Point[] p){
this.p = p;
}
void draw(){
System.out.printf("[p1=%s, p2=%s, p3=%s, color=%s]%n",
p[0].getXY(), p[1].getXY(), p[2].getXY(), color);
}
}
public class exCode {
public static void main(String[] args) {
Point[] p = {new Point(100, 100),
new Point(140, 50),
new Point(200, 100)
};
Triangle t = new Triangle(p);
Circle c = new Circle(new Point(150, 150), 150);
t.draw();
c.draw();
}
}
[실행 결과]
▶ Circle, Triangle 클래스는 Shape를 상속받는 관계이며, Point와는 포함관계를 맺고있다.
▶ main에서 point 인스턴스를 생성하면서 color를 지정하지 않았으나, 출력결과에는 black으로 나타난다. 이는 Shape 클래스에서 멤버변수로 정의해놓은 것을 상속받아 사용했기 때문이다.
# 예제2
class Deck{
final int CARD_NUM = 52;
Card cardArr[] = new Card[CARD_NUM];
Deck(){
int i=0;
for(int k=Card.KIND_MAX; k>0; k--){
for(int n=0; n<Card.NUM_MAX; n++){
cardArr[i++] = new Card(k, n+1);
}
}
}
Card pick(int index){
return cardArr[index];
}
Card pick(){
int index = (int) (Math.random()*CARD_NUM);
return pick(index);
}
void shuffle(){
for(int i=0; i<cardArr.length; i++){
int r = (int) (Math.random()*CARD_NUM);
Card temp = cardArr[i];
cardArr[i] = cardArr[r];
cardArr[r] = temp;
}
}
}
class Card{
static final int KIND_MAX = 4;
static final int NUM_MAX = 13;
static final int SPADE = 4;
static final int DIAMOND = 3;
static final int HEART = 2;
static final int CLOVER = 1;
int kind;
int number;
Card(){
this(SPADE, 1);
}
Card(int kind, int number){
this.kind = kind;
this.number = number;
}
public String toString(){
String[] kinds = {"", "CLOVER", "HEART", "DIAMOND", "SPADE"};
String numbers = "0123456789XJQK";
return "kind : " + kinds[this.kind] + ", number : " + numbers.charAt(this.number);
}
}
public class exCode {
public static void main(String[] args) {
Deck d = new Deck();
Card c = d.pick(0);
System.out.println(c);
d.shuffle();
c = d.pick(0);
System.out.println(c);
}
}
[실행 결과]
2. 제어자
클래스, 변수, 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여하는 것이다.
종류
- 접근 제어자 : public, protected, private, default
- 그 외 : static, final, abstract, native, transient, sunchronized, volatile, strictfp
접근 제어자는 한 번에 한가지만 사용할 수 있으며, 그 외의 제어자는 여러개를 조합하여 사용할 수 있다.
#제어자
◎ static : 클래스의, 공통적인
멤버변수, 메서드, 초기화 블럭에 사용할 수 있다.
인스턴스가 아닌 클래스에 관련된 것이므로 인스턴스를 생성하지 않아도 사용할 수 있다는 의미를 가진다.
◎ final : 마지막의, 변경될 수 없는
클래스, 메서드, 멤버변수, 지역변수의 거의 모든 곳에 사용할 수 있다.
변수에 사용하면 값을 변경할 수 없는 상수가 되고, 메서드에 사용하면 오버라이딩이 불가해진다. 클래스에 사용하면 자손클래스를 정의하지 못하게 된다는 의미이다.
◎ abstract : 추상의, 미완성의
클래스와 메서드에 사용할 수 있다.
추상 메서드를 선언할 때 많이 사용되는데, 이는 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않았다는 것을 의미한다. 클래스 앞에도 사용가능한데, 클래스 내에 추상 메서드가 선언되어 있다는 것을 알려준다.
#접근 제어자
클래스, 멤버변수, 메서드, 생성자에 사용 가능하다.
◎ public
접근 제한 없이 어디서든 접근이 가능하다.
◎ protected
같은 패키지 내 또는 다른 패키지의 자손클래스에서 접근이 가능하다.
◎ default
같은 패키지 내에서만 접근이 가능하다.
◎ private
같은 클래스 내에서만 접근이 가능하다.
접근범위 : public > protected > (default) > private
사용 시 주의사항
1. 메서드에 static과 abstract을 함께 사용할 수 없다.
2. 클래스에 abstract과 final을 동시에 사용할 수 없다.
3. abstract메서드의 접근 제어자로 private은 사용할 수 없다.
4. 메서드에 private과 final을 같이 사용할 수 없다.
'▶ JAVA > 개념정리' 카테고리의 다른 글
[Java] 12.객체지향언어(3)_클래스 (0) | 2022.03.08 |
---|---|
[Java] 11.객체지향언어(2)_클래스 (0) | 2022.03.07 |
[Java] 10. 객체지향언어(1)_클래스 (0) | 2022.02.10 |
[Java] 9. 배열_예제 (0) | 2022.02.07 |
[Java] 8. 배열 (0) | 2022.02.04 |