java 7일

KHLee·2023년 3월 3일

자바수업

목록 보기
7/46

OOP의 특징

  • 캡슐화(Encapsulation) : 객체의 필드, 메소드를 하나로 묶고, 실제 구현 내용을 감추는 것.
    캡슐화하여 보호하는 이유는 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록!
    접근제한자를 이용하여 캡슐화함.

  • 상속(Inheritance) : 부모 객체의 필드와 메소드를 하위 객체에게 물려주는 행위.
    상속 대상 : 필드, 메소드
    상위 객체를 재사용하여 하위 객체를 빨리 개발 가능, 반복된 코드의 중복을 줄임, 유지 보수의 편리성 제공

    UML에서 generation : 상속이다.

  • 다형성(Polymorphism) : 하나의 타입에 여러 가지 객체 대입해 다양한 실행 결과를 얻는 것.
    의미는 같지만 표현되어지는 것은 다르다!
    다형성을 구현하기 위한 전제조건은 상속이다.
    ex) draw()도형 <- draw()원, draw()삼각형, draw()사각형


화면과 기능을 분리해서 코딩한다?

package calculator;

public class Ui {

	public static void main(String[] args) {
		Calculator cal = new Calculator();
		int result = 0;
		result = cal.sum(10, 20);
		System.out.println(result);
		cal.save(result);//save는 void니깐 화면에서 리턴받을 게 없다. 너는 저장 해 끝!
		System.out.println("OK");//하지만 이 코드는 문제가 생긴지 안생긴지를 모른다.
								 //문제가 발생했을 때 오류를 출력해주는 것을 '예외처리'라고 한다!
	}

}
package calculator;

public class Calculator {
	public int sum(int a, int b) {
		int result = 0;
		result = a + b;
		return result;
	}
	public void save(int a){
		//뭔가 저장됨.
	}
}

상속과 오버라이딩과 다형성(매우중요!!)

package inherit;

public class Employee {
	private String id;
	private String name;
	private double salary;

	//getter, setter
	public double getSalary() {
		return salary;
	}
	
	//constructor
	public Employee() {
	}

	public Employee(String id, String name, double salary) {
		this.id = id;
		this.name = name;
		this.salary = salary;
	}
	//method
	public double getAnnSalary() {
		double result = 0.0;
		result = this.salary * 12;
		return result;
	}

	@Override
	public String toString() {
		return id + " " + name + " " + salary;
	}
	
}
package inherit;

public class Manager extends Employee {
	private double bonus;

	public Manager() {
		super();// 위에 있는 컨스트럭터 코드를 사용한다. 상속이 아님.
	} 			// 컨스트럭터는 불러서 사용하고 getter setter로 bonus만 불러와서 추가 컨스트럭터 생성 없이 이용도 가능.

	public Manager(String id, String name, double salary) {
		super(id, name, salary);
	}

	// constructor using field에서 Employee(String, String, double)을 선택하여 추가할 수 있다.
	public Manager(String id, String name, double salary, double bonus) {
		super(id, name, salary);
		this.bonus = bonus;
	}

	public double getBonus() {
		return bonus;
	}

	public void setBonus(double bonus) {
		this.bonus = bonus;
	}
	//함수의 재정의(overriding). 상속받은 함수를 그대로 쓸 수도 있다. 하지만 필요에 의해 오버라이딩할 수 있다.

	@Override//anotation주석이 붙는다.
	public double getAnnSalary() {
		double result = 0.0;
		result = (this.getSalary() + this.bonus) * 12;//private이라서 접근이 안됨. protected로 바꾸면 접근 가능
													  //또는 getter를 설정하여 가져오게 할 수 있음.
		//result = super.getAnnSalary() + (this.bonus * 12);
		//상위에 있는 getAnnSalary를 불러와서 계산할 수도 있다.
		return result;
	}

	@Override
	public String toString() {
		return super.toString() + " " + bonus;//상속받은 Employee의 toString을 super로 가져옴.
	}
	//source에서 toString을 누르면 inherited를 설정할 수 있다.
}
package inherit;

public class Sales extends Employee {
	private String loc;
	private double rate;
	public Sales() {
	}
	//기본 Employee 생성자를 source constructor from super에서 불러옴
	public Sales(String id, String name, double salary) {
		super(id, name, salary);
	}

	public Sales(String id, String name, double salary, String loc, double rate) {
		super(id, name, salary);
		this.loc = loc;
		this.rate = rate;
	}
	@Override
	public String toString() {
		return super.toString() + " " + loc + " " + rate;
	}
	@Override
	public double getAnnSalary() {
		double result = 0.0;
		result = super.getAnnSalary() + this.getIncentive() * 12;
		return result;
		}
	public double getIncentive() {
		double result = 0.0;
		result = getSalary() * this.rate;
		return result;
	}
	
}
package inherit;

public class App {

	public static void main(String[] args) {
		Employee e = new Employee("100", "james", 500);
		System.out.println(e);
		System.out.println(e.getAnnSalary());
		
		Manager m = new Manager("200", "Kim", 500, 50);
		System.out.println(m);//출력 시 Employee[]로 정보가 나옴.
							  //M is a E 의 관계가 성립한다. E is a M은 성립 안함.
							  //toString을 오버라이딩하는 경우 Manager로 정보를 나오게 할 수 있음.
		System.out.println(m.getAnnSalary());
	}

}
package inherit;

public class App2 {

	public static void main(String[] args) {
		//Manager is a Employee
		Employee e = new Manager("100", "james", 500, 50);
		//Manager m = new Employee("100", "james2", 550);//m은 e이지만 e는 m이 아니다.
		
		Employee ea[] = new Employee[5];
		ea[0] = new Employee("100", "james2", 500);
		ea[1] = new Employee("200", "james3", 500);
		ea[2] = new Manager("100", "james1", 500, 50);
		ea[3] = new Manager("100", "james4", 500, 50);
		ea[4] = new Sales("300", "jamess", 500, "seoul", 0.35);
		//배열을 생성할 때도, Manager는 Employee의 상속을 받았기 때문에 같은 배열로 들어갈 수 있다!
		
		for(Employee data : ea) {
			System.out.println(data);//출력 시 manager는 오버라이딩한 toString으로 출력됨.
			System.out.println(data.getAnnSalary());
			//연봉 가져와. Employee는 연봉만 가져오고 Manager는 bonus까지 합쳐서 연봉 산출해줌.
			//출력하는 것이 달라! 이것이 다형성. 상속을 활용하고 상속받은 것 내에서 오버라이딩을 하였음.
			if(data instanceof Sales) {
				Sales s = (Sales)data;
				//객체의 타입캐스팅; data 인스턴스 중 Sales인 것을 골라서 타입을 Sales로 변경해준다.
				System.out.println(s.getIncentive());
			}
			//data.getIncentive();//다형성에서 Sales 내 specialized된 함수는 보이지 않는다.
			//Sales가 Employee[]내에 선언되었기 때문에 Employee에 정의된 함수들만 data객체에서 확인할 수 있다.
			//다형성을 구현하기 위해선 상위 클래스의 함수를 잘 이용하여야 한다. 따라서 상위 클래스 함수를 잘 설계해야 한다!!!
			//database나 객체 설계를 하는 사람들은 원론적으로 설계를 하지만, 프로그래밍 할 때는 버거울 수가 있음.
			
			//따라서 위의 if문처럼 조건문과 객체의 타입캐스팅을 통해 인스턴스가 Sales인 것을 선별하고 형변환.
			//새로 형변환한 객체에서는 원래 Sales의 메소드 getIncentive를 사용할 수 있다.
		}
		
	}

}


Employee 메소드에 getIncentive가 없어서 다형성 구현이 어려웠지만 위처럼 Employee에 빈 메소드를 넣고 Sales에서 Override를 하는 방법으로도 다형성을 구현 가능!(Override안하고 getIncentive를 새로 만들 수 있지만 Override를 하여 상위 클래스와 같은 글자인지 확인할 수 있다.(@Override인데 메소드명 변경하면 빨간줄 나옴.)


자바에서는 오로지 하나의 클래스에서만 상속을 받을 수 있다.(단일 상속)

super(매개값) : 부모생성자 호출할 경우, 가장 윗줄에서 호출
부모 메소드 사용 : super
메소드 재정의는 부모 메소드 숨기는 효과!

메소드 재정의 : @Override => 이를 통해 폴리머피즘을 구현할 수 있다.
override한 경우 접근제어자를 부모보다 좁게 설정이 불가능하다.
(public -> private 불가능.)

final 키워드 : 더이상 재정의가 불가능하게 막는다!

  • final필드 : 수정불가 필드
  • final클래스 : 부모로 사용 불가한 클래스(상속 불가)
  • final메소드 : 자식이 재정의할 수 없는 메소드(오버라이드 불가)

다형성 - 상위 클래스의 함수를 알고 있으면 하위 클래스의 변경을 통해 다양한 효과를 만들어낼 수 있음. 하위 클래스에서 각 함수명을 통일해서 사용 가능(오버라이드)

Promotion(자동타입변환) : 자식클래스를 부모클래스 변수에 넣을 수 있다. 자동으로 타입 변환이 일어남. ex) Employee e = new Manager() 가능. 아래 예시.

package inherit2;

public class TaxCal {
	public double getTax(Employee e) {
		double result = 0.0;
		result = e.getAnnSalary() * 0.17;
		return result;
	}
}

Employee e라고 선언된 부분은 Manager Sales 다 들어갈 수 있다.


객체 타입 확인(instanceof) :
부모 타입이면 모두 자식 타입으로 강제 타입 변환할 수 있는 것은 아님.
먼저 자식 타입인지 확인 후 강제 타입 실행해야함.
if(parent instanceof Child){Child child = (Child) parent;

강제 타입 변환(Casting) : p.187
부모 타입을 자식 타입으로 변환하는 것
(조건 : 자식타입을 부모타입으로 자동변환 후, 다시 자식타입으로 변환할 때. ex) Manager -> Employee -> Manager)

Manager가 Employee로 선언이 되면 부모타입의 선언된 필드와 메소드만 사용이 가능한데, 자식타입에 선언된 필드와 메소드를 다시 사용해야 할 경우 Casting을 함.

profile
안녕하세요

0개의 댓글