프로그래밍/Java 공부

JAVA 상속

개발계발게발 2020. 12. 12. 15:14
반응형

자바에서는 클래스의 다중 상속을 지원 하지 않는다.

 

자바에서는 상속의 횟수에 제한을 두지 않는다.

 

자바에서 계층 구조의 최상위에 java.lang.Object 클래스가 있다.

 

 

슈퍼 클래스에 대한 접근 지정

슈퍼 클래스 멤버에 접근하는
클래스 종류
슈퍼 클래스 멤버의 접근 지정자
private 디폴트 protected public
같은 패키지에 있는 클래스 X O O O
다른 패키지에 있는 클래스 X X X O
같은 패키지에 있는 서브 클래스 X O O O
다른 패키지에 있는 서브 클래스 X X O O

슈퍼클래스의 private 멤버

 - private은 오직 현재클래스의 멤버들에게만 접근을 허용

 

슈퍼클래스의 디폴트 멤버

 - 패키지에 있는 모든 클래스 접근 가능, 다른 패키지의 서브 클래스 접근 X 

 

슈퍼클래스의 public 멤버

- 같은 패키지에 있든 다른 패키지에 있든 모든 클래스에서 접근 가능

 

슈퍼클래스의 protected 멤버

 - 같은 패키지의 모든 클래스 접근 가능

 - 같은 패키지든 다른 패키지든 상속받는 서브 클래스 접근 가능

 

클래스간 멤버 접근 예제

 

class Person{
	private int weight;
	int age;
	protected int height;
	public String name;
	
	public void setWeight(int weight) {
		this.weight=weight;
	}
	public int getWeight() {
		return weight;
	}
	
}

class Student extends Person{
	public void set() {
		age = 30;
		name = "홍길동";
		height = 175;
		//weight = 99; // 오류 슈퍼클래스 private 멤버 접근 불가
		setWeight(99);
	}
	public void show() {
		System.out.println("나이 : "+age+" 이름 : "+name+" 키 : "+height+" 몸무게 : "+getWeight()); // weight 호출시 함수 호출
	}
}

public class InheritanceEx {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Student s= new Student();
		s.set();
		s.show();

	}

}

- 슈퍼 클래스 A에 기본 생성자가 없는 경우, 오류 발생

- 서브 클래스 B의 매개변수를 가진 생성자도 슈퍼 클래스 A의 기본 생성자와 짝을 이룸

super()를 이용 )

: 슈퍼 클래스 생성자호출하는 코드

- 슈퍼 클래스 생성자를 명시적으로 선택할 수 ㅇ

- 반드시 생성자의 첫 라인에 사용되어야 함

(super(x); 이런거 써야 슈퍼 클래스 생성자 중에 A(int x) 이런거 쓸 수 있음)

타입 변환

업캐스팅(upcasting) : 서브 클래스의 객체에 대한 레퍼런스를 슈퍼 클래스 타입으로 변환하는 것

- 슈퍼 클래스의 레퍼런스로 서브 클래스의 객체를 가리키게 한다.

- 상위 클래스의 객체에 하위 클래스의 객체를 대입 = 단순화

class Person {
  String name;
  String id;
  .....
}
class Student extends Person {
  String grade;
  String department;
  .....
}
public class UpcastingEx {
  public static void main(String[] args) {
    Person p;
    Student s = new Student("강아지");
    p = (Person)s; //(Person)을 생략하고, p = s;로 해도 됨
    //업캐스팅
    System.out.println(p.name); //오류 없음

    p.grade = "A"; //컴파일 오류
    p.department = "Com"; //컴파일 오류
  }
}

다운캐스팅(downcasting) : 업캐스팅과 반대로 캐스팅

- 하위 클래스의 객체에 상위 클래스의 객체를 대입 = 세분화

//피라미드 생각하기, 그러면 위에서 아래로 내려오니까 세분화

//오른쪽 애가 왼쪽 애가 된다고 생각

//왼쪽 애 ← 오른쪽 애 이렇게;

Person p = new Student("강아지"); //업캐스팅 Student s = (Student)p; //다운캐스팅, (Student)의 타입 변환을 반드시 표시

레퍼런스 instanceof 클래스명

- 결과 값 : boolean 값

- '레퍼런스'가 가리키는 객체가 해당 '클래스' 타입의 객체이면 true 이고 아니면 false로 계산

- 클래스에만 적용

- 객체에 대한 레퍼런스만 사용

메소드 오버라이딩(method overriding)

: 슈퍼 클래스에 선언된 메소드와 같은 이름, 같은 리턴 타입, 같은 매개 변수 리스트를 갖는 메소드를 서브 클래스에서 재작성하는 것

= 슈퍼 클래스 메소드 무시하기 / 덮어쓰기

= 슈퍼 클래스의 메소드를 무시하고 서브 클래스에서 오버라이딩된 메소드가 무조건 실행되도록 한다는 것

: 어떻게 호출되든 객체 안에 오버라이딩된 메소드의 호출이 무조건 보장

: 슈퍼 클래스에 선언된 메소드를, 각 서브 클래스들이 자신만의 내용으로 새로 구현

: 상속을 통해 '하나의 인터페이스(같은 이름)에 서로 다른 내용 구현'이라는 객체 지향의 다형성 실현

= 동적 바인딩 dynamic binding (호출된 메소드를 실행 시간에 찾아서 실행하는 것)

// 동적 바인딩의 원리에 벗어나기 때문에 JAVA8 이전에 메소드를 static에서 벗어나게 했던 것이구낭 !!!!!

class Shape{//슈퍼 클래스
	public Shape next;
	public Shape() { next = null;}
	
	public void draw() {
		System.out.println("Shape");
	}
}

class Line extends Shape{
	public void draw() { // 메소드 오버라이딩
		System.out.println("Line");
	}
}

class Rect extends Shape{
	public void draw() { // 메소드 오버라이딩
		System.out.println("Rect");
	}	
}

class Circle extends Shape{
	public void draw() { // 메소드 오버라이딩
		System.out.println("Circle");
	}
}

public class MethodOverridingEx {
	static void paint(Shape p) {
		p.draw(); 
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Line line = new Line();
		
		// 다음 호출들은 모두 paint() 메소드 내에서 Shape에 대한 레퍼런스 p로 업캐스팅됨
		paint(line);	//	Line에 오버라이딩한 draw() 실행
		paint(new Shape()); // Shape에 오버라이딩한 draw() 실행
		paint(new Line());	// Line에 오버라이딩한 draw() 실행
		paint(new Rect());	// Rect에 오버라이딩한 draw() 실행
		paint(new Circle()); // Circle에 오버라이딩한 draw() 실행
		Shape start, last, obj;
		System.out.println("링크드 리스트 도형 생성 연결");
		//링크드리스트로 도형 생성 연결
		start = new Line(); // Line 객체 연결
		last = start;
		obj = new Rect(); // Rect 객체 연결
		last.next = obj;
		last = obj;
		obj = new Line(); // Line 객체 연결
		last.next = obj;
		last = obj;
		obj = new Circle(); // Circle 객체 연결
		last.next = obj;
		
		// 모든 도형 출력
		Shape p = start;
		while(p != null) {
			p.draw();
			p = p.next;
		}
	}
}

 

cf. 오버로딩(overloading) : 동일한 클래스 내(혹은 상속 관계)에서 메소드 이름이 같은데 매개변수가 다른 것들

@Override : 오버라이딩하는 메소드 앞에 붙여서, 다음 오버라이딩이 정확한지 컴파일러에게 확인하도록 지시

class Line extends Shape { @Override public void ... }

이 경우, 오류 메시지: The method ...( ) of type Line must override or implement a supertype method

1. 슈퍼 클래스의 메소드와 동일한 원형으로 작성

2. 슈퍼 클래스 메소드의 접근 지정자보다 접근의 범위를 좁여 오버라이딩 할 수 없다.

3. static이나 private 또는 final로 선언된 메소드는 서브 클래스에서 오버라이딩할 수 없다.

super

 

super.슈퍼클래스의멤버

super 키워드를 이용하면 정적 바인딩을 통해 슈퍼 클래스의 멤버에 접근 가능

class Shape{
	protected String name;
	public void paint() {
		draw();
	}
	public void draw() {
		System.out.println(name);
	}
}
public class Circle extends Shape {
	protected String name;
	@Override
	public void draw() {
		name = "Circle";
		super.name = "Shape";
		super.draw();
		System.out.println(name);
	}
	public static void main(String[] args) {
		Shape b = new Circle();
		b.paint();	
	}
}

 

 

cf. 

this - 생성자에서 다른 생성자를 호출할 때 사용

super - 서브 클래스의 생성자에서 슈퍼 클래스의 생성자를 호출할 때 사용

class Weapon{
	protected int fire() {
		return 1;
	}
}

class Cannon extends Weapon{
	@Override
	protected int fire() {
		return 10;
	}
}

public class Overriding {
	public static void main(String[] args) {
		Weapon weapon = new Weapon();
		System.out.println("기본 무기의 살상 능력은 "+ weapon.fire());
		
		weapon = new Cannon();
		System.out.println("대포의 살상 능력은 "+ weapon.fire());
	}
}

 

추상메소드

추상 메소드(abstract method) : 선언은 되어 있으나 코드가 구현되어 있지 않은 메소드 (abstract 키워드 필요)

= 메소드의 프로토타입만 있고 실행 코드를 작성하지 않은 미완성의 메소드

- 추상 메소드를 가지고 있으면 → 무조건 추상 클래스로 선언

cf. 추상 메소드를 하나도 가지고 있지 않아도 추상 클래스 선언 가능

- 추상 클래스는 객체를 혹은 인스턴스를 생성할 수 x

- 서브 클래스에서 추상 클래스에 선언된 추상 메소드를 모두 구현해야함

= 추상 클래스를 상속받고 추상 메소드를 오버라이딩하지 않으면 상속받은 클래스도 추상 클래스가 된다.

package 상속;

abstract class Calculator{
	public abstract int add(int a, int b);
	public abstract int subtract(int a, int b);
	public abstract double average(int[] a);
}


public class GoodCalc extends Calculator {

	@Override
	public int add(int a, int b) {

		return a+b;
	}

	@Override
	public int subtract(int a, int b) {

		return a-b;
	}

	@Override
	public double average(int[] a) {
		double sum = 0;
		for (int i = 0; i<a.length; i++)
			sum +=a[i];
		return sum/a.length;
	}
	public static void main(String[] args) {
		GoodCalc c = new GoodCalc();
		System.out.println(c.add(2, 3));
		System.out.println(c.subtract(2, 3));
		System.out.println(c.average(new int [] {2,3,4}));

	}

}

 

인터페이스

자바의 인터페이스(interface)

- interface 키워드를 사용하여 클래스를 선언하듯이 선언 (일종의 추상 클래스)

(말그대로 어떤 interface, 규격을 주는 용도)

1. 멤버는 추상 메소드와 상수만으로 구성

2. 모든 메소드는 abstract public 이며 생략 가능 + default 가능 + private 가능 + static 가능

3. 상수는 public static final 타입이며 생략 가능

4. 인터페이스는 객체를 생성할 수없다

5. 다른 인터페이스에 다중 상속 가능 ㅇ : extends 키워드 사용

6. 인터페이스 타입의 레퍼런스 변수는 선언 가능

 

default 메소드의 접근지정은 public으로 고정

private 메소드는 인터페이스 내에서만 호출 가능

static 메소드는 접근 지정이 생략되면 public 이며, private으로 지정될수 있다.​

 

 

인터페이스 구현 (implements 키워드 사용)

: 인터페이스의 추상 메소드를 모두 구현한 클래스를 작성, 추가적으로 다른 메소드 작성 가능

- 클래스에서 인터페이스의 메소드를 구현할 때 public 생략하면 오류 발생

package 상속;

interface PhoneInterface{
	public static final int TIMEOUT = 10000;	//상수 필드, public static final 생략 가능
	public abstract void sendCall();	// 추상 메소드. public abstract 생략 가능
	public abstract void receiveCall(); 	// 추상 메소드. public abstract 생략 가능
	public default void printLogo() {	// default 메소드. public 생략 가능
		System.out.println("** Phone **");
	}
}

class SamsungPhone implements PhoneInterface{
	// PhoneInterface의 모든 메소드 구현
	
	@Override
	public void sendCall() {
		System.out.println("띠리리리링");
		
	}
	@Override
	public void receiveCall() {
		System.out.println("전화가 왔습니다.");
		
	}
	
	public void flash() {
		System.out.println("전화기에 불이 켜졌습니다.");
	}
	
	
}


public class InterfaceEx {

	public static void main(String[] args) {
		SamsungPhone phone = new SamsungPhone();
		phone.printLogo();
		phone.sendCall();
		phone.receiveCall();
		phone.flash();
	}

}

 

클래스 상속과 함께 인터페이스 구현

package 상속;

interface PhoneInterface{
	public static final int TIMEOUT = 10000;	//상수 필드, public static final 생략 가능
	public abstract void sendCall();	// 추상 메소드. public abstract 생략 가능
	public abstract void receiveCall(); 	// 추상 메소드. public abstract 생략 가능
	public default void printLogo() {	// default 메소드. public 생략 가능
		System.out.println("** Phone **");
	}
}
interface MobilePhoneInterface extends PhoneInterface{ //인터페이스 상속
	void sendSms();
	void receiveSMS();
}

interface Mp3InterFace{ //인터페이스 선언
	public void play();
	public void stop();
}
class PDA{ //클래스 작성
	public int calculate(int x, int y) {
		return x + y;
	}	
}

// SmartPhone 클래스느 PDA를 상속받고
// MobilePhoneInterface와 MP3Interface 인터페이스에 선언된 추상 메소드를 모두 구현한다.

class SmartPhone extends PDA implements MobilePhoneInterface, Mp3InterFace{
	//MobilePhoneInterface의 추상 메소드 구현
	@Override
	public void sendCall() {
		System.out.println("따르릉따르릉~~");
		
	}

	@Override
	public void receiveCall() {
		System.out.println("전화 왔어요");
		
	}
	
	@Override
	public void sendSms() {
		System.out.println("문자를 전송합니다.");
		
	}

	@Override
	public void receiveSMS() {
		System.out.println("문자 왔어요");
		
	}
	
	//MP3Interface의 추상 메소드 구현
	
	@Override
	public void play() {
		System.out.println("음악을 재생합니다.");
		
	}

	@Override
	public void stop() {
		System.out.println("음악을 중단합니다.");
		
	}
	
	// 추가 작성 메소드
	public void schedule() {
		System.out.println("일정 관리합니다.");
	}


	
}

public class InterfaceEx {

	public static void main(String[] args) {
		SmartPhone phone = new SmartPhone();
		phone.printLogo();
		phone.sendCall();
		phone.play();
		System.out.println("3과 5를 더하면 " + phone.calculate(3, 5));
		phone.receiveCall();
		phone.schedule();
	}

}

 

= 인터페이스는 클래스의 규격

비교 목적 구성
추상 클래스 추상 클래스는 서브 클래스에서 필요로 하는 대부분의 기능을 구현하여 두고 서브 클래스가 상속받아 활용할 수 있도록 하되, 서브 클래스에서 구현할 수밖에 없는 기능만을 추상 메소드로 선언하여, 서브 클래스에서 구현하도록 하는 목적(다형성) - 추상 메소드와 일반 메소드 모두 포함
- 상수, 변수 필드 모두 포함
인터페이스 인터페이스는 객체의 기능을 모두 공개한 표준화 문서와 같은 것으로, 개발자에게 인터페이스를 상속받는 클래스의 목적에 따라 인터페이스의 모든 추상 메소드를 만들도록 하는 목적(다형성)

Because an interface is supposed to mean "what you can see from outside the class".
- 변수  필드(멤버 변수)는 포함하지 않음

- 상수, 추상 메소드, 일반 메소드,
   default 메소드, static 메소드 모두 포함

- protected 접근 지정 선언 불가

- 다중 상속 지원

반응형