JAVA Study
1. 상속 (inheritance)
- 기존 클래스를 재사용하여 새로운 클래스를 작성하는 것
- 보다 적은 양의 코드로 새로운 클래스 작성 가능 & 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이
- 새로 작성하고자 하는 클래스 이름 뒤에 상속받고자 하는 클래스의 이름을 키워드 'extends'와 함께 써줌
class child extends parent{
// parent 클래스를 상속받은 child 클래스
}
- 상속해주는 클래스를 조상클래스, 상속 받는 클래스를 자손클래스라고 함
: 조상클래스 - 부모 클래스, 상위클래스, 기반 클래스
: 자손클래스 - 자식 클래스, 하위클래스, 파생된 클래스
- 자손 클래스는 조상 클래스의 모든 멤버를 상속 받음
: child 클래스는 parent 클래스의 모든 멤버들을 포함
: child 클래스에 새로운 코드가 추가되어도 조상인 parent클래스는 아무 영향을 받지 않음
: 자손클래스는 조상 클래스의 모든 멤버를 상속받으므로 항상 조상 클래스보다 같거나 많은 멤버를 갖음
- 생성자와 초기화 블럭은 상속되지 않음, 멤버만 상속
- 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많음
class parent { }
class child extends parent { }
class child2 extends parent { }
: child와 child2클래스 모두 parent클래스를 상속받음
: 클래스 간 관계에서 형제관계는 없음
: child와 child2 클래스에 공통적으로 추가되어야 하는 멤버변수나 메서드가 있다면 공통조상인 parent에 작성
class parent { }
class child extends parent { }
class grandchild extends child{ }
: 자손 클래스는 조상 클래스의 모든 멤버를 물려받으므로 grandchild클래스는 child 클래스의 모든 멤버, child클래스의 조상인 parent 클래스로부터 상속받은 멤버까지 상속받게 됨
: grandchild 클래스는 child의 자손이면서 parent의 자손이기도 함
: child클래스는 grandchild클래스의 직접조상, parent 클래스는 grandchild 클래스의 간접 조상이 됨
: parent클래스에 변수를 추가하면 parent를 상속받고 있는 child, grandchild클래스에 변수가 공통적으로 추가됨
- 자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버도 함께 생성되므로 따로 조상클래스의 인스턴스를 생성하지 않아도 조상클래스의 멤버들을 사용할 수 있음
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | class Tv{ boolean power; //전원상태 on/off int channel; //채널 void power(){ power = !power; } void channelUp(){ ++channel; } void channelDown(){ --channel; } } class CaptionTv extends Tv{ boolean caption; //캡션상태 on/off void displayCaption (String text){ if(caption){ //캡션 상태가 on(true)일 때만 text를 보여준다. System.out.println(text); } } } public class CaptionTvTest{ public static void main(String[] args) { CaptionTv t = new CaptionTv(); //자손 클래스의 인스턴스를 생성하면 조상클래스의 변수와 메서드를 사용할 수 있다. t.channel = 10; // 조상 클래스에서 상속받은 멤버 t.channelUp(); // 조상 클래스에서 상속받은 멤버 System.out.println(t.channel); // channel은 11 t.displayCaption("Hello world1"); // 캡션 상태가 on이 아니므로 출력되지 않음 t.caption = true; t.displayCaption("Hello world2"); // Hello world2 출력 } } | cs |
- 클래스간의 관계 (포함관계)
: 클래스 간에 포함관계를 맺어 상속외에 클래스를 재사용하는 방법
: 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것을 뜻함
1 2 3 4 5 6 7 8 9 10 | class Circle{ int x; // 원점의 x좌표 int y; // 원점의 y좌표 int r; // 반지름 } class Point{ int x; // x좌표 int y; // y좌표 } | cs |
: Point 클래스를 재사용해서 Circle 클래스를 작성
1 2 3 4 5 6 7 8 9 | class Circle{ Point c = new Point(); //원점 int r; // 반지름 } class Point{ int x; // x좌표 int y; // y좌표 } | cs |
- 클래스간의 관계 결정하기
: 상속관계를 맺을 지, 포함관계를 맺을지 결정
- ~은 ~이다. : 상속관계
- ~은 ~을 가지고 있다. : 포함관계
ex. 원은 점이다 / 원은 점을 가지고 있다. => 원은 점을 가지고 있다가 더 자연스러우므로 포함관계를 맺는 것이 옳다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | class DrawShap{ 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),50); t.draw(); //삼각형을 그린다 c.draw(); //원을 그린다 } } class Shap{ String color="black"; void draw(){ System.out.print("color = "+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+")"; //x와 y의 값을 문자열로 반환 } } class Circle extends Shape{ Point center; int r; Circle(){ this(new Point(0,0),100); // Circle(Point center,int r)를 호출 } Circle(Point Center, int r){ this.center =center; this.r = r; } void draw(){ //원을 그리는 대신에 원의 정보를 출력하도록 했다. System.out.print(""); } } class Triangle extends Shape { Point[] p = new Point[3]; Triangle(Point[] p){ this.p = p; } void draw(){ System.out.print("[p1]=("+p[0].getXY()+"), [p2]=("+p[1].getXY()+"), [p3]=("+p[2].getXY()+")"); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | package apple2; public class DectTest { 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); //뽑은 카드 확인 } } class Deck{ final int CARD_NUM =52; // 카드의 개수 Card cardArr[] = new Card[CARD_NUM]; // Card 객체 배열 포함 Deck(){ // 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(){ // Deck에서 카드하나 선택 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"; //숫자10은 X로 표현 return "kind : "+kinds[this.kind] + ", number : "+numbers.charAt(this.number); } } | cs |
- 단일 상속 (Single inheritance)
: 자바는 단일상속만을 허용한다 -> 하나 이상의 클래스로부터 상속받을 수 없음
- Object 클래스 - 모든 클래스의 조상
: Object 클래스는 모든 클래스 상속계층도의 최상위에 있는 조상클래스
: 다른 크랠스로부터 상속 받지 않는 모든 클래스들은 자동적으로 Object클래스로부터 상속받게 함
: 모든 클래스의 조상이 되는 클래스
: 만일 다른 클래스를 상속받더라도 상속계층도를 따라 조상클래스를 올라가다보면 마지막 최상위 조상은 Object클래스임
2. 오버라이딩 (overriding)
- 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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; } } | cs |
: Point 클래스의 getLocation() 은 한 점의 x,y좌표를 문자열로 반환하도록 작성되었다.
: 이 두 클래스는 서로 상속관계에 있으므로 Point3D클래스는 Point 클래스로부터 getLocation()을 상속받은 후 자신에 맞게 z축의 좌표를 포함하여 반환하도록 오버라이딩 하였다
- 오버라이딩 조건
: 자손클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와 이름 / 매개변수 / 반환타입이 같아야 한다
: 선언부가 서로 일치해야 함
: 접근 제어자와 예외는 제한된 조건 하에서만 다르게 변경할 수 있음
- 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없음
- 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없음
- 인스턴스메서드를 static메서드로 또는 그 반대로 변경할 수 없음
- 오버로딩 vs 오버라이딩
: 오버로딩 (overloading) - 기존에 없는 새로운 메서드를 정의하는 것(new)
: 오버라이딩(overriding) - 상속받는 메서드의 내용을 변경하는 것(change, modify)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; } String getLocation(int i){ //오버로딩 } } | cs |
- super
: 자손클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수
: 멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이 상속받은 멤버와 자신의 클래스에 정의된 멤버의 이름이 같을 때 super를 붙여서 구별할 수 있음
: 조상 클래스로 상속받은 멤버도 자손 클래스의 멤버이므로 super대신 this를 사용할 수 있음
: 조상 클래스의 멤버와 자손클래스의 멤버가 중복 정의되어 서로 구별해야하는 경우에만 super를 사용하는 것이 좋음
: 모든 인스턴스변수에는 자신이 속한 인스턴스 주소가 지역변수로 저장되는데, 이것이 참조변수인 this와 super의 값이 됨
: static메서드는 인스턴스와 관련없기때문에 super를 사용할 수 없음 (인스턴스에서만 사용할 수 있음)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; return super.getLocation() + ", z : "+z; //조상 메서드 호출 } } | cs |
: 조상클래스의 메서드의 내용에 추가적으로 작업을 덧붙이는 경우 super를 사용해 조상클래스의 메서드를 포함시키는 것이 좋음
- 후에 조상 클래스의 메서드가 변경되더라도 변경된 내용이 자손클래스의 메서드에 자동적으로 반영될 것이기 때문
- super()
: 조상 클래스의 생성자를 호출하는데 사용됨
: 자손 클래스의 인스턴스를 생성하면, 자손과 조상의 멤버가 모두 합쳐진 하나의 인스턴스가 생성되는데, 이 때 조상 클래스 멤버의 초기화 작업이 수행되어야 함 -> 자손클래스의 생성자에서 조상 클래스의 생성자를 호출
: Object클래스를 제외한 모든 클래스의 생성자의 첫 줄에서 조상클래스의 생성자를 호출, 그렇지 않으면 컴파일러가 생성자의 첫 줄에 'super();'를 자동적으로 생성
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | class PointTest { public static void main (String args[]) { Point3D p3 = new Point3D(1,2,3); } } class Point { int x, y; Point(int x, int y) { this.x = x; this.y = y; } String getLocation() { return "x : "+x+", y : "+y; } } class Point3D extends Point { int z; Point3D(int x, int y, int z) { super(x,y); // 조상클래스 생성자 // this.x = x; // this.y = y; this.z = z; } String getLocation() { return "x : "+x+", y : "+y+", z : "+z; } } | cs |
'프로그래밍 > JAVA' 카테고리의 다른 글
[JAVA] 7 객체지향 프로그래밍 2-3 (0) | 2017.07.22 |
---|---|
[JAVA] 7 객체지향 프로그래밍 2-2 (0) | 2017.07.21 |
[JAVA] 6 객체지향 프로그래밍1 (0) | 2017.07.05 |
[JAVA] 배열 예제 (0) | 2017.07.04 |
[JAVA] 5 배열 (Array) (0) | 2017.07.03 |