자바 기초 프로그래밍 4일차

awarduuu·2023년 3월 7일
0

230307

1. 정보 은닉

Data(속성)를 외부의 접근으로부터 보호하기 위한 방법, 코드의 유지보수를 용이하게 함

Class Student{
	private String name;
	private int age; // 18 보다 큰 나이만 허용 가능!
}

Student st = new Student();
st.age=2; 
/*
오류는 아니지만 시나리오 입장에서는 오류이다!!
이러한 모호한 데이터가 수정되거나 조회되지 않도록 
개발자가 제공하는 대로만 조회 = getXxx(), 수정 = setXxx()할 수 있도록 메소드를 제공한다!
*/

구현 방법

1) setXxx 규칙

  • 제한자 : public
  • 리턴타입 : void
  • 메소드 이름 : set필드명(필드Type 변수);
  • 인수 : 필수

2) getXxx 규칙

  • 제한자 : public
  • 리턴타입 : 필수
  • 메소드 이름 : get필드명();
  • 인수 : 없음

2. 상속

상속이란 부모(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();
		}
}

3. 다형성

  • 반드시 상속관계일 때 성립

  • 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);
		}

4. Overriding(재정의)

상속관계에서 Super(부모) class에 정의되어 있는 method를 Sub(자식) class에서 재정의 하는 것

㉠ modifier의 접근제한자는 반드시 부모 class의 제한자 보다 크거나 같아야
한다.
⇨ 접근제한자 이외의 modifier(abstract)는 같아도 달라도 상관없다.
㉡ returnType 무조건 같다.
㉢ method이름, 인수 무조건 같다.
㉣ 기능을 다르게 만든다.
⇨ 즉, 부모 class의 method 기능이 마음에 들지 않아 다른 기능으로 재정의.


5. this 와 super

this

생성된 현재 객체를 뜻한다

  • this.변수이름 : 현재객체안에 있는 전역변수를 뜻한다.

  • this.메소드이름(값, 값,....) : 현재 객체안에 있는 메소드를 호출

  • this(값, 값,....) : 현재 객체안에 있는 생성자를 호출(반드시 생성자구현부 첫번째줄에서만 가능)

super

상속관계일때 자식 안에서 부모를 부를 때 사용하는 키워드

  • super.변수이름 : 부모클래스안에 있는 전역변수를 뜻한다.

  • super.메소드이름(값, 값,....) : 부모클래스안에 있는 메소드를 호출

  • super(값, 값,....) : 부모클래스에 있는 생성자를 호출(반드시 생성자구현부 첫번째줄에서만 가능)


6. 상속관계일 때 생성자 개념

① 모든 자식 생성자 구현부 첫번째 줄에는 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의 비밀

println(Object obj) 메소드는 인수로 객체가 전달되면 obj.toString()를 자동으로 호출한다.
그 다음, toString이 리턴하는 값을 출력한다.

Object 클래스의 toString() 메소드는 getClass().getName() + "@" + 해시코드
출력하는 기능이다.

String 클래스는 Object를 상속받은 클래스로 toString() 메소드를 자기자신의 문자열을 출력하는 기능으로 오버라이딩한 것이다.

따라서, 객체의 toString() 함수를 오버라이딩하여 객체의 출력형식을 재정의하는 현명한 방법을 사용할 수 있다!!

profile
선한 영향력을 만드는 개발자

0개의 댓글