상속
◆상속의 장점◆
● 상속을 통해서 클래스를 작성하면 적은 양의 코드로 새로운 클래스를 작성가능
● 코드의 추가 및 변경이 매우 용이하다
● 코드의 재사용성을 높이고 중복을 제거, 유지보수 향상, 생산성 향상
class Child extends Parent{ //자바 상속하는 키워드 extends
//.....
}
조상 클래스 = 부모 클래스, 상위 클래스, 기반 클래스
자손 클래스 = 자식 클래스, 하위 클래스, 파생된 클래스
상속은 IS A 관계
▼
생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다.
▼
자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
class Tv {
boolean power;
int channel;
void power(){ power = !power;}
void channelUp() {++channel;}
void channelDown(){--channel;}
}
class CaptionTv extends Tv{
boolean caption;
void displayCaption(String text){
if(caption){
System.out.println(text);
}
}
}
class CaptionTvTest{
public static void main(String args[]){
CaptionTv ctv = new CaptionTv();
ctv.channel =10;//조상 클래스로 부터 상속받은 멤버
ctv.channelUp();//조상 클래스로 부터 상속받은 멤버
ctv.channel; //11
}
}
클래스 간의 포함 관계 is a , has 코드 예시
class Circle{
Point c = new Point();
int r;
}
has a 관계 원은 점을 가지고 있다.
class Circle extends Point{
int r;
}
is a 원은 점이다
Is a , has a full example of code
class DrawShape{
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 Point{
int x,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(){
//.. 출력문 center.x, center.y, r, color
}
}
class Triangel extends Shape{
Point[] p = new Point[3];
Triangle(Point[] p){
this.p = p;
}
void draw(){
System.out.println("p1=%s, p2=%s, p3=%s,color=%s"),
p[0].getXY(),p[1].getXY(), p[2].getXY(), color);
}
}
class Shape{
String color ="black";
void draw(){
System.out.println("color=%s",color);
}
}
원은 도형이다.
원은 점을 가지고 있다.
오버라이딩 예시 : 조상클래스에 정의된 메서드와 같이 메서드를 자손 클래스에 정의하는 것을 오버라이딩이라고 하며, 곧이어 배울 내용
class Shape{
String color ="black";
void draw(){
System.out.println("color=%s",color);
}
}
class Circle extends Shape{
void draw(){
System.out.println("center=%d, %d, r=%d,color=%s",
center.x, center.y, r, color);
}
}
오버라이딩의 조건
▶ 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와 "이름이 같아야 한다."
▶ 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와"매개변수가 같아야 한다."
▶ 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와"반환타입이 같아야 한다."
접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.
◈ 조상 클래스의 메서드를 자손 클래스에서 오버라이딩할 때 ◈
▶ 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
▶ 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
▶ 인스턴스메서드를 static 메서드로 또는 그 반대로 변경할 수 없다.
자바는 다중상속을 허용하지 않는다. 한 클래스를 조상으로 하고 타 클래스를 포함 시키면 포함 시킨 클래스에서 메서드와 일치하는 선언부를 가진 사용할 수 있다.
class Tv{
boolean power;
int channel;
void power{ power = !power;}
void channelUp(){++channel;}
void channelDown(){--channel;}
}
class VCR{
boolean power;
int counter =0;
void power() { power = !power;}
void paly(){///.....}
void stop(){///.....}
void rew(){///.....}
void ff(){///.....}
}
class TVCR extends Tv{
VCR vcr = new VCR();//vcr 포함 시켜서 인스턴스화 후에 호출
void play(){
vcr.play();
}
void stop(){
vcr.stop();
}
void rew(){
vcr.rew();
}
void ff(){
vcr.ff();
}
}
super의 설명 : super는 자손 클래스에서 조상 클래스로 부터 상속받은 멤버를 참조하는데 사용되는 참조 변수이다.
멤버변수와 지역변수 이름이 같을 때 this를 붙여 구별하듯 상속받은 멤버와 자신의 멘버와 이름이 같을 때 super로 구분
class SuperTest{
public static void main(String args[]){
Child c = new Child();
c.method();
}
}
class Parent{
int x =10;
}
class Child extends Parent{
void method(){
System.out.println("x="+x);//10
System.out.println("this.x" + this.x);//10
System.out.println("super.x" + super.x);//10
}
}
super.x는 조상 클래스로부터 상속받은 멤버변수 x를 뜻하며, this.x는 자손 클랫에 선언된 멤버변수
♣sper를 이용한 오버라이딩♣
class Point{
int x,y;
String getLocation(){
return "x: " +x +"y:" +y;
}
}
class Point3d extends Point{
int z;
String getLocation(){
return super.getLocation() + ", :" +z;
}
}
this는 같은 클래스의 다른 생성자를 호출하는 데 사용되지만, super()는 조상 클래스의 새성자를 호출하는데 사용된다.
sper 사용시 주의할 점
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()를 삽입한다/.
this.x = x;
this.y = y;
this.z = z;
}
}
컴파일 에러 발생함 Point3D클래스의 생성자에서 조상 클래스의 생성자 Point를 찾을 수 없음
solution for above code
Point3D(int x, int y, int z){
super();
this.x = x;
this.y = y;
this.z = z;
}
Point3D(int x, int y, int z){
super(x, y);
this.z = z;
}
class PointTest2{
public static void main(String args[]){
Point 3D p3 = new Point3D();
System.out.println("p3.x=",p3.x);
System.out.println("p3.y=",p3.y);
System.out.println("p3.z=",p3.z);
}
}
class Point{
int x=10;
int y =20;
Point(int x, int y){
super();//조상인 object 클래스의 생성자 object클래스 호출
this.x = x;
this.y =y;
}
}
class Point3D extends Point{
int z =30;
Point3D(){
this(100, 200,300);//Point3D x, y , z를 호출
}
Point3D(int x, int z, int z){
super(x,y);//Point x,y호출
this.z =z;
}
}
제어자
제어자의 종류는 크게 접근 제어자 그외로 나눈다.
접근 제어자 : public,protected, default, private
그 외 static ,final, abstract, native, transient, synchronized, volatile, strictfp
| static | 멤버변수 | -모든 인스턴스에 공통적으로 사용되는 클래스변수가 된다. -클래스변수는 인스턴스를 생성하지 않고도 사용 가능하다. -클래스가 메모리에 로드될 때 생성된다. |
|||
| 메서드 | 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다. |
static 메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다. |
|||
| final | 클래스 | 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다.. final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다. |
| 메서드 | 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다. | |
| 멤버변수 | 변수 앞 final이 붙으면 값을 변경할 수 ㅇㅂ서는 상수가 된다. | |
| 지역변수 |
final class FinalTest{//FINAIL사용시 조상이 될 수 없다.
final int MAX_SIZE =10;//값을 변경할 수 없는 멤버변수
final void getMaxSize(){
final int LV = MAX_SIZE; // 오버라이딩할 수 없는 메서드
return MAX_SIZE;// 값을 변경할 수 없는 지역변수
}
}
abstract는 미완성의 의미를 가지고 있다. 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언한는데 사용
제어자의 접근 범위
| public > protected > default > private |
접근 제어자를 이용한 캡슐화
▶ 클래스나 멤버, 주로 벰버에 접근 제어자를 사용하는 이유는 클래스의 내부에 선언된 데이터를 보호하기 위해서
▶ 내부 작업을 위해 임시로 사용되는 멤버변수나 부분작업을 처리하기 위한 메서드 등의 멤버들을 클래스 내부에 감추기 위해서
| 접근 제어자를 사용하는 이유 ▶ 외부로부터 데이터를 보호하기 위해서 ▶ 외부에는 불필요한, 내부적으로만 사용되는,부분을 감추기 위ㅣ해서 |
| ▶ 메서드에 static과 abstract를 함께 사용할 수 없다. - > static메서드는 몸통이 있는 메서드에만 사용가능 ▶ 클래스에 abstract와 final을 동시에 사용할 수 없다. -> 클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미 abstract는 상속을 통해서만 완성을 해야한다는 의미로 모순된다. ▶ abstract 메서드의 접근 제어자가 private일 수 없다. -> 왜냐하면 자손에서 구현해야 하기 때문에 ▶ 메서드에 private과 final을 같이 사용할 필요는 없다 |