다형성
다형성을 이해하기 위해 알아야 할 것
1. 상속
2. 오버라이딩
3. 추상클래스(abstract, interface)
4. 객체의 형변환
- 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하는 것.
반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다.
- 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스 멤버 개수보다 같거나 적어야 한다.
(자식이7개, 조상이5개이면 안 된다는 뜻)
참조변수의 형변환
: 사용할 수 있는 멤버의 갯수를 조절하는 것.
- 서로 상속관계에 있는 클래스사이에서만 가능하다.
=> 자손타입의 참조변수를 조상타입의 참조변수로, 조상타입의 참조변수를 자손타입의 참조변수로의 형변환만 가능
=> 부모객체에 자식객체를 담을 수 있다(부모 <----- 자식).
자식객체에 부모객체를 담을 수 없다(자식 <--x-- 자식).
//객체의 형변환
class Super{
String name = "페데리코";
public void display() {
System.out.println("super의 display");
}
}
class Sub extends Super{
String name = "bts";
public void display() {
System.out.println("sub의 display");
}
public void test() {
System.out.println("sub의 test");
}
}
class Sub2 {
}
public class RefTypeCstingTest {
public static void main(String[] args) {
System.out.println("1. Super타입의 참조변수로 Super객체를 접근");
Super obj1 = new Super();
obj1.display();
System.out.println(obj1.name);
System.out.println("*************************************");
System.out.println("1. Sub타입의 참조변수로 Sub객체를 접근");
Sub obj2 = new Sub();
System.out.println(obj2.name);
obj2.display(); //상속관계에서 오버라이딩된 메소드가 있는 경우 오버라이딩된 메소드가 우선 실행됨
System.out.println("*************************************");
System.out.println("3. Super타입의 참조변수로 Sub객체를 접근");
Super obj3 = new Sub(); // Sub를 Super타입으로 바꾸겠다는 뜻. 변수타입을 Super로 바꾸는 것,
// 하지만 Sub, Super 둘 다 갖고 있음
// 뒤에 있는 애가 앞에 있는 애보다 커야 한다(내용물이).
System.out.println(obj3.name); //Super타입이라 "페데리코" 출력됨
// obj3이 참조하는 객체가 Sub타입인 경우 명시적 캐스팅가능
((Sub)obj3).test();
obj3.display();
System.out.println("*************************************");
System.out.println("4. Sub타입의 참조변수로 Super객체를 접근");
//Sub obj4 = new Super(); // 실제 사용되는 변수타입에 대한 정보가 생성되는 객체에없기
// 때문에 객체를 참조할 수 없다.
System.out.println("*************************************");
System.out.println("5. Sub변수 = Super객체를 참조하는 변수");
// 명시적으로 캐스팅하면 컴파일러는 속일 수 있으나(상속관계에 있어야만 속는다.)
// obj1이 참조하는 객체가 Super이므로 런타임 시 오류가 발생한다.
//Sub obj5 = (Sub)obj1; //Sub obj5 = new Super();
System.out.println("6. Sub변수 = Sub객체를 참조하는 Super 변수 ------ 가능함");
System.out.println("*************************************");
Sub obj6 = (Sub)obj3;
// obj3이 참조하는 객체가 Sub타입이면 true를 반환
// obj3이 Sub타입이 아니면 false를 반환
if(obj3 instanceof Sub) {
System.out.println("Sub타입");
}else {
System.out.println("Sub타입아님");
}
if(obj1 instanceof Sub) {
System.out.println("Sub타입");
}else {
System.out.println("Sub타입아님");
}
}
}
// 변수끼리 있을 때
Sub obj6 = (Sub)obj3;
---
ㄴ> 얘가 기준!!
* obj3의 타입을 Sub로 바꾸겠다는 뜻
Sub타입으로 바꾸려면 (왼쪽의)Sub가 Super, Sub 둘 다 갖고 있어야 함
=> obj3를 Sub타입으로 바꿔서 obj6(참조변수)에 넣겠다는 뜻
* Super 변수명 = new 객체(<- Super의자손들)
ㄴ> Super만 담고 있으면 됨
Sub 변수명 = new 객체
ㄴ> Sub, Super 둘 다 담고 있어야 함(Sub는 Super를 상속받았기 때문에)
추상클래스
=> 객체를 생성할 수 없는 클래스. 즉, 모든 구현되어 있지 않은 클래스(미완성된 클래스)
내용이 구현되지 않은 메소드를 포함하고 있는 클래스를 추상클래스라 한다.
추상메소드(body가 없는 메소드)
1) 추상메소드를 선언하는 방법
▶ 접근제어자 abstract 리턴타입 메소드명(매개변수list...);
2) 추상클래스의 특징
- 일반메소드와 추상메소드를 모두 정의할 수 있다.
- 추상메소드가 하나라도 정의되어 있으면 클래스 선언부에 abstract를 추가한다.
- 추상클래스는 객체생성을 할 수 없는 클래스
- 추상클래스를 상속받는 클래스는 extends하면 에러가 발생
=> SuA가 SuperA를 상속받는다. SuperA의 모든 멤버가 SubA의 소유 -> 따라서 SubA도 추상메소드를 갖는 추상클래스가 된다.
<에러처리>
* SubA앞에 abstract을 추가한다.
* 상속받은 abstract메소드를 구현한다(메소드의 body를 정의한다.).
- abstract클래스는 상위클래스로 만들기 위해서 사용(상위클래스로 정의되고 타입으로 사용하기 위해서 사용)
- abstract메소드는 하위클래스에서 반드시 오버라이딩되어야 한다는 것을 문법적으로 제시
abstract class SuperA{
public void test() { //일반메소드
System.out.println("test");
}
public abstract void display(); //추상메소드
}
class SubA extends SuperA{
@Override
public void display() {
System.out.println("display");
}
}
public class AbstractTest {
public static void main(String[] args) {
SubA obj = new SubA();
obj.display();
}
}
제어자 final
package oop.inheritance;
import java.security.PublicKey;
class AA {
static final int MY_VAL = 10000; //멤버변수에 final이 추가되면 상수. 상수는 대문자로 쓰기
public final void display() { //메소드 앞에 final이 추가되면 오버라이딩이 불가능한 메소드가 됨
System.out.println("AA");
//myval = 1000;
}
}
final class BB extends AA {
public void display() { // 오류 -> 조상 클래스의 선언부에서 final이 있기 때문에
// 부모가 갖고 있는 display를 재정의(오버라이딩)
System.out.println("BB");
}
}
public class FinalTest {
public static void main(String[] args) {
BB obj = new BB();
obj.display();
}
}
<예제>
package oop.polymorphism;
public class TestShape {
public static void main(String[] args) {
Shape [] shape = new Shape[2];
shape[ 0 ] = new Circle("원",10);
shape[ 1 ] = new Rectangular("직사각형",10,20);
for (int i = 0; i < shape.length; i++) {
shape[ i ].calculationArea();
shape[ i ].print();
}
}
}
위의 조건을 구현하기
// 조상 클래스
public abstract class Shape {
private double area; //면적
private String name; //이름
public Shape(){
}
public Shape(String name) {
super();
this.name = name;
}
public abstract void calculationArea();
public void print() {
System.out.println(name+"의 면적은 "+area);
}
public double getArea() {
return area;
}
public void setArea(double area) {
this.area = area;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 자손 클래스
public class Circle extends Shape {
private double radius; //반지름
public Circle() {
}
public Circle(String name, double radius) {
super(name);
this.radius = radius;
}
public void calculationArea() {
setArea(Math.PI*radius*radius);
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
}
// 자손 클래스
public class Rectangular extends Shape {
private double width;
private double height;
public Rectangular() {
}
public Rectangular(String name, double width, double height) {
super(name);
this.width = width;
this.height = height;
}
public void calculationArea() {
setArea(height*width);
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
}
* 추상클래스 이용하기
'JAVA' 카테고리의 다른 글
2022-10-21 java.lang패키지와 유용한 클래스(API활용법) (0) | 2022.10.22 |
---|---|
2022-10-18 객체지향언어 - 인터페이스, 예외처리방법 1. try-catch / 2. 예외선언하기(throw, throws) (0) | 2022.10.22 |
2022-10-14 객체지향언어 - 생성자, 상속 (0) | 2022.10.17 |
2022-10-13 객체지향언어 - 배열, 클래스 메소드(static메소드)와 인스턴스 메소드 (0) | 2022.10.13 |
2022-10-11~12 객체지향언어 - 메소드 작성방법, 호출, 오버로딩, 캡슐화, 생성자 +활용 (0) | 2022.10.12 |
댓글