Java 개념 정리 (2)

hjseo-dev·2021년 8월 7일
0

Java

목록 보기
2/3
post-thumbnail

📍 접근제한자

클래스 내에서 멤버의 접근을 제한하는 역할

✏️ 접근제한자 종류

  1. public : 어떤 클래스에서도 접근 가능
  2. protected : 자기자신, 같은 패키지, 상속관계 에서만 접근 가능
  3. private : 자기 자신만 접근 가능
  4. default : 접근 제한자가 없을 경우 같은 패키지에서만 접근 가능
    ex)
  public class AccessObj{
        private int i = 1;
        int k = 2; // default 접근 제한자
        public int p = 3;
        protected int p2 = 4;
    }
  
  public class AccessObjExam{
        public static void main(String args[]){
            AccessObj po = new AccessObj();

            System.out.println(po.i); // 컴파일 오류 발생(private)
            System.out.println(po.k);
            System.out.println(po.p);
            System.out.println(po.p2);
        }
    }

📍 추상클래스

구체적이지 않은 클래스를 의미 ex) 독수리, 타조 등은 구체적인 새를 지칭하는 것인데 새, 포유류 같은 것은 구체적이지 않음

✏️ 정의하기

  1. 추상 클래스는 클래스 앞에 abstract 키워드를 이용해서 정의한다.
  2. 추상 클래스는 미완성의 추상 메소드를 포함할 수 있다.
  3. 추상 메소드란, 내용이 없는 메소드 이다. 즉 구현이 되지 않은 메소드이다. 리턴 타입 앞에 abstract라는 키워드를 붙여야 한다.
  4. 추상 클래스는 인스턴스를 생성할 수 없다.
 public abstract class Bird{  //추상클래스
        public abstract void sing();  //추상메소드 => 상속 받은 곳에서 구현해야 한다

        public void fly(){
            System.out.println("날다.");
        }
    }

✏️ 추상클래스 상속

  1. 추상 클래스를 상속받은 클래스는 추상 클래스가 갖고 있는 추상 메소드를 반드시 구현해야 한다.
  2. 추상 클래스를 상속받고, 추상 클래스가 갖고 있는 추상 메소드를 구현하지 않으면 해당 클래스도 추상 클래스가 된다.
    public class Duck extends Bird{
        @Override //오버라이드로 상속 받은 메소드를 만들어준다
        public void sing() {
            System.out.println("꽥꽥!!");
        }
    }
    
    //사용하는 법
    public class DuckExam { 
        public static void main(String[] args) {
            Duck duck = new Duck();
            duck.sing();
            duck.fly();

            //Bird b = new Bird(); -> 추상 클래스여서 객체를 생성할 수 없다
        }   
    }

📍 super와 부모생성자

class가 인스턴스화 될때 생성자가 실행되면서 객체의 초기화를 한다. 그 때 자신의 생성자만 실행이 되는것이 아니고, 부모의 생성자부터 실행된다.

  public class Car{
        public Car(){
            System.out.println("Car의 기본생성자입니다.");
        }
    }

    public class Bus extends Car{
        public Bus(){
            System.out.println("Bus의 기본생성자입니다.");
        }

    }
  //생성자 테스트
  public class BusExam{
        public static void main(String args[]){
            Bus b = new Bus();
        }
    }
    
Car의 기본생성자입니다.
Bus의 기본생성자입니다.

new 연산자로 Bus객체를 생성하면, Bus객체가 메모리에 올라갈때 부모인 Car도 함께 메모리에 올라간다.
생성자가 호출될 때 자동으로 부모의 생성자가 호출되면서 부모객체를 초기화 하게된다.

📍 super

자신을 가리키는 키워드가 this 라면, 부모를 가리키는 키워드는 super
super() 는 부모의 생성자를 의미한다.
부모의 생성자를 임의로 호출하지 않으면, 부모 class의 기본 생성자가 자동으로 호출된다.
아래 예제처럼 호출해보면 위에서 super()를 호출하지 않을때와 결과가 같다.

    public Bus(){
        super();
        System.out.println("Bus의 기본생성자입니다.");
    }

💡 부모클래스에 기본 생성자가 없을 경우는?

    public class Car{
        public Car(String name){
            System.out.println(name + " 을 받아들이는 생성자입니다.");
        }
    }

이런 경우 자식 클래스에서 컴파일 오류가 나므로 직접 부모의 생성자를 호출하기 위해 super();를 사용한다

public Bus(){
        super("소방차"); // 문자열을 매개변수로 받는 부모 생성자를 호출하였다.
        System.out.println("Bus의 기본생성자입니다.");
    }

📍 오버라이딩

오버라이딩이란 부모가 가지고 있는 메소드와 똑같은 모양의 메소드를 자식이 가지고 있는 것이다. 즉 오버라이딩이란 메소드를 재정의 하는 것이다.

✏️ 메소드 오버라이딩

ex) 부모의 run 메소드를 자식한테 상속하여 이름이 같은 run 메소드를 재정의 하여 표현

//run 메소드를 가지고 있는  Car클래스 
    public class Car{
        public void run(){
            System.out.println("Car의 run메소드");
        }
    }

    //Car 를 상속받는 Bus 클래스 
    public class Bus extends Car{
		 public void run(){  //메소드 제정의
            System.out.println("Bus의 run메소드");
        }
    }

    public class BusExam{
        public static void main(String args[]){
            Bus bus = new Bus();
            bus.run();  //Bus의 run메소드가 실행된다. 
        }
    }

이렇게 재정의를 통해 결과는 자식클래스에서 선언한 메소드로 나온다. 하지만 부모의 메소드는 사라지지 않고 남아있다. super();를 통해서 호출가능!

public class Bus extends Car{
        public void run(){
            **super.run();**  // 부모의  run()메소드를 호출 
            System.out.println("Bus의 run메소드");
        }
    }

📍 클래스 형변환

부모타입에서 자식객체가 가지고 있는 메소드나 속성을 사용하고 싶다면 형변환 해야 한다.

   public class Car{
        public void run(){
            System.out.println("Car의 run메소드");
        }
    }

    public class Bus extends Car{
        public void ppangppang(){
            System.out.println("빵빵.");
        }   
    }

Bus에서 Car를 상속받으면, 부모인 Car타입으로 자식을 참조했을 때 오류 발생한다.

    public class BusExam{
        public static void main(String args[]){
            Car car = new Bus();
            car.run();
            car.ppangppang(); // 컴파일 오류 발생
        }
    }

부모 타입에서 자식타입의 객체를 참조 할때 명시적 형변환을 통해 가능하다.
자식 객체를 생성할 때 부모객체 앞에 ()로 명시해 주면 가능

    public class BusExam{
        public static void main(String args[]){
            Car car = new Bus();
            car.run();
            //car.ppangppang(); // 컴파일 오류 발생

            Bus bus = (Bus)car;  //부모타입을 자식타입으로 형변환 
            bus.run();
            bus.ppangppang();
        }
    }

0개의 댓글