728x90
반응형
Contents
코드의 통일성을 더 향상시키기 위한 방법 : 업캐스팅 활용
실습 1
Circle 인스턴스 (C) 생성
Circle c = new Circle();
c.circlePaint();
c.draw();
System.out.println("--------------------------");
// Rectangle
Rectangle r = new Rectangle();
r.rdraw();
r.draw();
System.out.println("--------------------------");
//Triangle
Triangle t = new Triangle();
t.design();
t.draw();
여러 도형의 특징을 공통적으로 포함하는 슈퍼클래스 Shape 정의
class Shape {
//여러 도형의 공통점인 '그리다' 기능을 수행하는 draw () 메서드 정의
public void draw() {
System.out.println("도형 그리기!");
}
}
//Shape 클래스를 상속받는 Circle 클래스 정의
class Circle extends Shape {
public void circlePaint() {
System.out.println("원 그리기!");
}
}
//Shape 클래스를 상속 받는 Rectangle 클래스 정의
class Rectangle extends Shape{
public void rdraw() {
System.out.println("사각형 그리기");
}
}
//Shape 클래스를 상속받는 Triangle 클래스 정의
class Triangle extends Shape {
public void design() {
System.out.println("삼각형 그리기");
}
}
circle, rectangle, triangle 의 공통 슈퍼 클래스인 Shape 타입 s 으로 세 인스턴스를 컨트롤 가능
Circle -> Shape 업캐스팅
Shape s = new Circle();
s.draw(); //동적바인드에 의해 Circle 인스턴스의 draw() 메서드 호출
//Rectangle -> Shape 업캐스팅
s = new Rectangle();
s.draw(); // Rectangle 인스턴스의 draw() 메서드 호출
//Triangle -> Shape 업캐스팅
s = new Triangle();
s.draw();
다형성을 배열에 적용시키는 경우
슈퍼클래스 타입으로 배열을 생성해서 배열의 각 인덱스에 각 각 서브클래스 인스턴스를 저장 가능
shape 타입 배열을 생성 (크기가 3)
Shape[] sArr = new Shape[3];
0번 인덱스에 Circle 인스턴스를 생성하여 저장
sArr[0] = new Circle();
Circle -> Shape에 업캐스팅을 한 것.
1번 인덱스에 Rectangle 인스턴스를 생성하여 저장
sArr[1] = new Rectangle();
2번 인덱스에 Triangle 인스턴스를 생성하여 저장
sArr[2] = new Triangle();
위의 3코드를 하기 코드로 나타낼 수 있다.
Shape[] sArr = {new Circle(), new Rectangle(), new Triangle()};
sArr[0].draw();
sArr[1].draw();
sArr[2].draw();
배열의 각 인덱스에는 인스턴스 주소가 저장되므로, 참조변수와 마찬가지로
배열명[인덱스].메서드명() 형태로 호출 가능
for(int i =0; i <sArr.length; i++){
sArr[i].draw();
}
메서드 - 다형성 활용
1. 이미 다형성이 적용된 배열을 메서드 파라미터로 전달
Ex2 ex = new Ex2();
ex.polymorphismDraw();
} //main()
public void polymorphismDraw() {
} // Ex2
static이 설정되지 않은 인스턴스 메서드를 호출 하는 경우
먼저 인스턴스를 생성하고 호출 할 수 있다.
반면, static 설정되어 있는 '클래스(정적) 메서드'를 호출하는 경우
인스턴스를 생성하지 않아도클래스명.메서드 형태로 호출이 가능!
이 때, 자신의 클래스 내부에서 정의한 '클래스(정적) 메서드' 라면 클래스명은 생략도 가능하다.
public static void polymorphismDraw(Shape[] sArr) {
for (int i = 0; i < sArr.length; i++) {
sArr[i].draw();
}
}
반복문을 사용하여 배열 내의 모든 인스턴스의 draw() 메서드 호출
2. 메서드 파라미터로 인스턴스를 전달
//2. 메서드 파라미터로 인스턴스를 전달
polymorphismDraw2(new Circle());
polymorphismDraw2(new Rectangle());
polymorphismDraw2(new Triangle());
}//main
public static void polymorphismDraw2(Shape s) {
//어떤 인스턴스가 전달 되더라도 draw() 메서드는 공통이므로 호출 가능!
s.draw();
}
전체
package polymorphism;
public class Ex2 {
public static void main(String[] args) {
// Circle 인스턴스 (C) 생성
Circle c = new Circle();
c.circlePaint();
c.draw();
System.out.println("--------------------------");
// Rectangle
Rectangle r = new Rectangle();
r.rdraw();
r.draw();
System.out.println("--------------------------");
//Triangle
Triangle t = new Triangle();
t.design();
t.draw();
System.out.println("--------------------------");
//코드의 통일성을 더 향상시키기 위한 방법 : 업캐스팅 활용
// => circle, rectangle, triangle 의 공통 슈퍼 클래스인
// Shape 타입 s 으로 세 인스턴스를 컨트롤 가능
// Circle -> Shape 업캐스팅
Shape s = new Circle();
s.draw(); //동적바인드에 의해 Circle 인스턴스의 draw() 메서드 호출
//Rectangle -> Shape 업캐스팅
s = new Rectangle();
s.draw(); // Rectangle 인스턴스의 draw() 메서드 호출
//Triangle -> Shape 업캐스팅
s = new Triangle();
s.draw();
System.out.println("---------------------------------------");
// 다형성을 배열에 적용시키는 경우
// 슈퍼클래스 타입으로 배열을 생성해서 배열의 각 인덱스에 각 각 서브클래스 인스턴스를 저장 가능
Shape[] sArr = new Shape[3]; //shape 타입 배열을 생성 (크기가 3)
//0번 인덱스에 Circle 인스턴스를 생성하여 저장
sArr[0] = new Circle();
sArr[1] = new Rectangle();
sArr[2] = new Triangle();
// sArr[0].draw();
// sArr[1].draw();
// sArr[2].draw();
for(int i =0; i <sArr.length; i++){
sArr[i].draw();
}
//이미 다형성이 적용된 배열을 메서드 파라미터로 전달
polymorphismDraw2(sArr);
//2. 메서드 파라미터로 인스턴스를 전달
polymorphismDraw2(new Circle());
polymorphismDraw2(new Rectangle());
polymorphismDraw2(new Triangle());
}//main
public static void polymorphismDraw2(Shape[] sArr) {
for (int i = 0; i < sArr.length; i++) {
sArr[i].draw();
}
}
public static void polymorphismDraw2(Shape s) {
//어떤 인스턴스가 전달 되더라도 draw() 메서드는 공통이므로 호출 가능!
s.draw();
}
}//Ex2
//여러 도형의 특징을 공통적으로 포함하는 슈퍼클래스 Shape 정의
class Shape {
//여러 도형의 공통점인 '그리다' 기능을 수행하는 draw () 메서드 정의
public void draw() {
System.out.println("도형 그리기!");
}
}
//Shape 클래스를 상속받는 Circle 클래스 정의
class Circle extends Shape {
public void circlePaint() {
System.out.println("원 그리기!");
}
}
//Shape 클래스를 상속 받는 Rectangle 클래스 정의
class Rectangle extends Shape{
public void rdraw() {
System.out.println("사각형 그리기");
}
}
//Shape 클래스를 상속받는 Triangle 클래스 정의
class Triangle extends Shape {
public void design() {
System.out.println("삼각형 그리기");
}
}
실습 2
package polymorphism;
public class Ex3 {
public static void main(String[] args) {
Employee emp = new Employee("홍길동",3000);
System.out.println("Employee 정보 : " + emp.getEmployee());
emp.salaryCalculation();
Manager man = new Manager("이순신",4000,"개발팀",3);
System.out.println("Manager 정보 : " + man.getManager());
System.out.println("Manager 정보 : " + man.getEmployee());
man.salaryCalculation();
Engineer eng = new Engineer("강감찬", 5000, 5);
System.out.println("Engineer 정보 : " + eng.getEngineer());
System.out.println("Engineer 정보 : " + eng.getEmployee());
eng.salaryCalculation();
System.out.println("================================================");
//다형성 적용시키기
//각 인스턴스의 salaryCalculationAll() 메서드를 호출하여
//자신의 인스턴스를 파라미터로 전달
emp.salaryCalculationAll(emp);
// => emp.salaryCalculation(new Employee("홍길동",3000)); 이렇게 써도 됨.
man.salaryCalculationAll(emp);
eng.salaryCalculationAll(eng);
}
}
//직원 클래스 정의
class Employee{
String name;
int salary;
public Employee(String name, int salary) {
super(); //Object 클래스의 Object() 생성자 호출
this.name = name;
this.salary = salary;
}
public String getEmployee() {
return name + ", " + salary;
}
//일반 직원의 연봉 계산(기본 연봉을 그대로 적용)
public void salaryCalculation() {
System.out.println("연봉 : " + salary);
}
//전 직원의 연봉을 슈퍼클래스인 Employee 클래스에서 모두 계산 하고싶다면, 다형성이 필요하다.
//(employee, Manager, Engineer 인스턴스 모두 처리)
// 따라서, 메서드 파라미터로 다형성을 적용한 Employee 타입 필요.
public void salaryCalculationAll(Employee emp) { //업캐스팅됨
int salaryResult = 0; //연봉 계산 결과를 저장할 변수
//*******************************************************************************************************************
//참조 영역의 축소로 인해 각 서브클래스 타입 멤버변수는 보이지 않음
//=> Employee를 제외한 Manager, Engineer 의 경우
// 다시 다운캐스팅을 통해 각 클래스에서 정의한 멤버에 접근해야 한다!
//=> 단, 무작정 다운캐스팅을 수행할 경우 오류가 발생할 수 있으므로
// 반드시 instanceof 연산자를 통한 타입 판별 후 다운캐스팅 필요
//=> 주의! 반드시 하위타입부터 판별을 수행해야 한다.
//*******************************************************************************************************************
//가장 큰 개념인 Employee를 맨 마지막에 써줘야한다?
//*******************************************************************************************************************
if(emp instanceof Manager) { //Manager 타입인가?
//Employee -> Engineer 타입으로 다운캐스팅 가능
System.out.println("Employee -> Engineer 로 다운캐스팅");
// Manager man = emp; //자동 형변환 불가, 강제형변환 해야햄
Manager man = (Manager) emp;
//업캐스팅으로 축소됐던 참조영역이 다운캐스팅으로 확대되었으므로
//다운캐스팅 된 Manager 타입 인스턴스를 통해 모든 멤버변수 접근 가능
//기본 영본과 관리 ㅣㅇㄴ원 수에 따른 인센티브를 더해서 계산
salaryResult = man.salary + man.manageEmployeeCount * 10;
} else if(emp instanceof Engineer) { //Engineer 타입인지?
// Engineer eng = emp; //자동 형변환 불가, 강제형변환 해야햄
Engineer eng = (Engineer) emp;
salaryResult = eng.salary + eng.numOfCertificate * 20;
}else if(emp instanceof Employee) { //Employee 타입인지?
System.out.println("Employee 그대로 사용!");
salaryResult = salary;
}
//각 직원의 계산된 연봉 출력
System.out.println("연봉 : " + salaryResult + "만원 입니다!");
}
}
//관리자 Manager 클래스 정의 - Employee 상속
class Manager extends Employee{
String depart; //부서명
int manageEmployeeCount; //관리하는 직원 수
//슈퍼클래스 기본생성자가 없으므로 파라미터 생성자를 호출하는 생성자 정의
public Manager(String name, int salary, String depart, int manageEmployeeCount) {
super(name, salary);
this.depart = depart;
this.manageEmployeeCount = manageEmployeeCount;
}
public String getManager() {
// return name + ", " + salary + ", " + depart + ", " + manageEmployeeCount + "명";
return getEmployee() + ", " + depart + ", " + manageEmployeeCount + "명";
}
@Override
public void salaryCalculation() {
int salaryResult = salary + manageEmployeeCount * 10;
System.out.println("연봉 : " + salaryResult);
}
// Employee 의 연봉 계산 메서드를 오버라이딩
// => 매니저 연봉은 기본 연봉 + (관리직원 수 * 10만원)
}
//엔지니어(Engineer) 클래스 정의 - Employee 상속
class Engineer extends Employee {
int numOfCertificate; //자격증 개수
public Engineer(String name, int salary, int numOfCertificate) {
super(name, salary);
this.numOfCertificate = numOfCertificate;
}
public String getEngineer() {
return getEmployee() + ", " + numOfCertificate + "개";
}
//Employee 의 연봉 계산 메서드를 오버라이딩
// 엔지니어 연봉은 기본 연봉 + (자격증 수 * 20만원)
@Override
public void salaryCalculation() {
int salaryResult = salary + (numOfCertificate * 20);
System.out.println("연봉 : " + salaryResult);
}
}
728x90
반응형
'BackEnd > Java' 카테고리의 다른 글
1012 JAVA - Interface 인터페이스 - 문제 (0) | 2022.10.12 |
---|---|
1006 JAVA - 상수, 인터페이스 (0) | 2022.10.06 |
1005 JAVA - 동적 바인딩 , 정적 바인딩 (0) | 2022.10.05 |
0929 JAVA - Instanceof 연산자 (1) | 2022.09.29 |
0929 JAVA - Polymorphism 다형성 (2) | 2022.09.29 |