Data(속성)를 외부의 접근으로부터 보호하기 위한 방법, 코드의 유지보수를 용이하게 함
Class Student{
private String name;
private int age; // 18 보다 큰 나이만 허용 가능!
}
Student st = new Student();
st.age=2;
/*
오류는 아니지만 시나리오 입장에서는 오류이다!!
이러한 모호한 데이터가 수정되거나 조회되지 않도록
개발자가 제공하는 대로만 조회 = getXxx(), 수정 = setXxx()할 수 있도록 메소드를 제공한다!
*/
1) setXxx 규칙
2) getXxx 규칙
상속이란 부모(Super) Class의 속성(전역변수 = Feild)과 method를 상속 받는 것
부모 class의 생성자와 private 요소를 제외한 모든 것을 상속받는다.
단일 상속만 가능
extends 키워드 사용
class A extends B {} // A가 B를 상속 받는다.
java의 모든 class는 Object(Class)를 상속받는다. (생략되어있음)
아래의 예시 경우 Customer와 Employee는 People을 상속 받는 클래스이다. 하지만 이 두 클래스는 People를 각각 상속받는다 (공유하는 의미가 아님). (부모 : People)
package day04;
class Car{ // 부모 클래스
public String carname;
public int cost;
protected void printAttributes(){
System.out.println("carname="+carname+"\tcost="+cost);
}
}
//Car를 상속받는 EfSonata, Excel, Carnival 3개 클래스 작성
//각 클래스에 인수를 받지않는 생성자 작성
//각 클래스의 생성자의 구현부에서 carname과 cost에 적당한 값 할당
class EfSonata extends Car {
// 생성자의 접근제한자는 class의 접근제한자를 따라간다 ex) 생략 -> 생략
EfSonata(){
super.carname = "EfSonata";
super.cost = 50_000_000;
}
}
class Excel extends Car {
Excel(){
super.carname = "Excel";
super.cost = 30_000_000;
}
}
class Carnival extends Car {
Carnival(){
super.carname = "Carnival";
super.cost = 40_000_000;
}
}
public class InheritanceExam{
//메인메소드에서
//Car, EfSonata, Excel, Canival 네개의 객체를 생성
// 각 클래스에서 Car calss에있는 printAttributes()메소드를 호출할수있다.
public static void main(String[] args) {
Car car = new Car();
car.carname = "ferrari";
car.cost = 100_000_000;
EfSonata efSonata = new EfSonata();
Excel excel = new Excel();
Carnival carnival = new Carnival();
car.printAttributes();
efSonata.printAttributes();
excel.printAttributes();
carnival.printAttributes();
}
}
반드시 상속관계일 때 성립
class A extends B {} 일 때 A를 A라 부를 수 있고 A를 B라 부를 수 있다.
즉, 접근 범위가 달라진다.
㉠ A a = new A(); ⇨ O
㉡ B b = new A(); ⇨ O
㉢ B c = new B(); ⇨ O
㉣ A d = new B(); ⇨ X
package day04;
class CarCenter{
// 매개변수를 이용한 다형성
public void engineer(Car cd){
System.out.print(cd.carname+" 수리완료!\t");
System.out.println("청구비용"+cd.cost+" 원");
}
}
public class PolymorphismExam{
public static void main(String[] args) {
CarCenter cc=new CarCenter();
EfSonata ef=new EfSonata();
Carnival ca=new Carnival();
Excel ex=new Excel();
Car c= new Car();
cc.engineer(c);//
cc.engineer(ef);//
cc.engineer(ca);//
cc.engineer(ex);//
}
}
ObjectDownCasting를 활용해 객체도 캐스팅을 활용할 수 있다.
단, 상속관계일때만 가능하다.
class CarCenter{
// 매개변수를 이용한 다형성
public void engineer(Car cd){
System.out.println("cd = " + cd);
// System.out.println(cd.a);; => error!!! 부모타입으로는 자식부분 접근 불가이기 때문
// 접근이 가능하도록 하기 위해서는 ObjectDownCasting을 한다.
Carnival car = (Carnival) cd; // 부모 > 자식이기 때문에 Down
System.out.println("car = " + car);
System.out.println("car.a = " + car.a);
System.out.print(cd.carname+" 수리완료!\t");
System.out.println("청구비용"+cd.cost+" 원");
}
}
instanceof 연산자를 통해 객체타입이 될 수 있는지 여부를 확인 가능하다.
if(cd instanceof Carnival) { // 상속관계일때만 사용가능 (Carnival은 Car의 자식이기 때문에 가능)
Carnival car = (Carnival) cd; // 부모 > 자식이기 때문에 Down
System.out.println("car = " + car);
System.out.println("car.a = " + car.a);
}
상속관계에서 Super(부모) class에 정의되어 있는 method를 Sub(자식) class에서 재정의 하는 것
㉠ modifier의 접근제한자는 반드시 부모 class의 제한자 보다 크거나 같아야
한다.
⇨ 접근제한자 이외의 modifier(abstract)는 같아도 달라도 상관없다.
㉡ returnType 무조건 같다.
㉢ method이름, 인수 무조건 같다.
㉣ 기능을 다르게 만든다.
⇨ 즉, 부모 class의 method 기능이 마음에 들지 않아 다른 기능으로 재정의.
생성된 현재 객체를 뜻한다
this.변수이름 : 현재객체안에 있는 전역변수를 뜻한다.
this.메소드이름(값, 값,....) : 현재 객체안에 있는 메소드를 호출
this(값, 값,....) : 현재 객체안에 있는 생성자를 호출(반드시 생성자구현부 첫번째줄에서만 가능)
상속관계일때 자식 안에서 부모를 부를 때 사용하는 키워드
super.변수이름 : 부모클래스안에 있는 전역변수를 뜻한다.
super.메소드이름(값, 값,....) : 부모클래스안에 있는 메소드를 호출
super(값, 값,....) : 부모클래스에 있는 생성자를 호출(반드시 생성자구현부 첫번째줄에서만 가능)
① 모든 자식 생성자 구현부 첫번째 줄에는 super(); 가 생략되어있다.
② 반드시 부모의 기본 생성자가 필요하다.
③ 부모의 생성자가 하나도 없으면 기본 생성자가 자동 삽입되므로 문제 없다.
④ 부모의 기본 생성자가 없다면, 다른 생성자만 있다면 클래스를 확장하기 어렵기 때문에 기본 생성자를 생성하는 것을 권장한다. 따라서 this(값), super(값) [다른생성자]를 생성자 구현부 첫줄에 강제로 호출해야한다.
중요 문법!!
부모타입 변수로 재정의 된 메소드를 호출하면 무조건 자식부분이 호출된다!
package day04.superEx;
class Animal {
int legs = 4;
String name ="name";
Animal(){
System.out.println("Aniaml() 1...");
}
Animal(int i){
System.out.println("Animal(int i) 2...");
}
Animal(String s){
System.out.println("Animal(String s) 3....");
}
/*
* 소리낸다.
* */
public void sound() {
System.out.println("Rrrrrrr");
}
/*
* 달린다
* */
public void run() {
System.out.println("호다닥");
}
}
class Pig extends Animal {
int legs = 2;
int age = 5;
Pig(){
this(4); // super가 없어졌다. Pig(int i)를 호출했기 때문
System.out.println("Pig() 3...");
// //변수 접근!
// System.out.println(legs); //2
// System.out.println(this.legs); //2
// System.out.println(super.legs); //4
//
// //변수 접근!
// System.out.println(name); //name
// System.out.println(this.name); //name
// System.out.println(super.name); //name
//
// //변수 접근!
// System.out.println(age); //5
// System.out.println(this.age); //5
//// System.out.println(super.age); //error
}
Pig(int i){
super(i); // Animal(int i)를 호출
System.out.println("Pig(int i) 4...");
}
Pig(boolean b){
super(b+"안녕"); // Animal(String s)를 호출
System.out.println("Pig(boolean b) 5...");
}
//재정의
@Override
public void sound() {
System.out.println("꿀꿀");
}
@Override
public void run() {
System.out.println("터벅");
}
public void eat() {
System.out.println("너무 많이 먹는다~");
}
}
public class SuperConstructorExam {
public static void main(String[] args) {
// TODO Auto-generated method stub
Pig pig = new Pig();
// 모든 자식 생성자 구현부 첫번째 줄에는 super(); 가 생략되어있다.
// 반드시 부모의 기본 생성자가 필요하다.
// 부모의 생성자가 하나도 없으면 기본 생성자가 자동 삽입되므로 문제 없다.
pig.sound(); // 재정의
pig.run(); // 재정의 안함
System.out.println("-----다형성------");
Animal animal = new Pig();
System.out.println(animal.legs);
System.out.println(animal.name);
animal.sound(); // **중요** Rrrr가 아닌 꿀꿀이 나온다
// animal.eat(); // 자식 부분에만 있는 메소드는 접근이 불가능하다.
if(animal instanceof Pig) {
Pig p = (Pig) animal;
System.out.println(p.age);
p.eat();
}
}
}
println(Object obj) 메소드는 인수로 객체가 전달되면 obj.toString()를 자동으로 호출한다.
그 다음, toString이 리턴하는 값을 출력한다.
Object 클래스의 toString() 메소드는 getClass().getName() + "@" + 해시코드를
출력하는 기능이다.
String 클래스는 Object를 상속받은 클래스로 toString() 메소드를 자기자신의 문자열을 출력하는 기능으로 오버라이딩한 것이다.
따라서, 객체의 toString() 함수를 오버라이딩하여 객체의 출력형식을 재정의하는 현명한 방법을 사용할 수 있다!!