본문 바로가기

카테고리 없음

#3 <3주차> 다형성과 추상화

가변길이 매개변수 선언 spread

void carSpeeds(double ... speeds){
 for(double v: speeds){
  System.out.println("v=" + v);
}
}

 

 

참조형변수 기본형 변수 차이
-참조는 주소를 가르킴
-기본형은 값을 복사해서 가져옴

 

클래스 멤버 사용 시 클래스의 이름으로 접근한다
String companyName=Car.getCompany("Benz");
**참조형 변수를 사용하여 클래스 멤버에 접근 가능하지만 추천하지 않음

 

 

 

 

this와 this()의 차이

this는 인스턴스 자신을 가르키는 참조변수
this()는 생성자를 가르킴 
static 메서드에서는 this를 사용하지 못함

this() 로 다른 생성자 호출 이전에 코드가 존재하면 오류 발생

public Car(String model){
 System.out.println("model="+model);
this(model, "blue", 500000);  ->> 안됨
}

 

 

 

접근 제어자

public 접근 제한 전혀 없음
protected 같은 패키지 내에서 다른 패키지의 자손 클래스에서 접근이 가능
default 같은 패키지 내에서만 접근이 가능
private 같은 클래스 내에서만 접근이 가능

 

 

사용가능한 제어자

클래스: public default final abstract
메서드 : public protected default private final abstract static
메서드 : public protected default private final abstract static
지역변:  final

 

 

제어자 사용 시 주의 사항
메서드에 static과 abstract를 함께 사용할 수 없다
클래스에 abstract와 final을 동시에 사용할 수 없다
메서드에 private와 final을 같이 사용할 필요 없다

 

 

**다른패키지의 생성자를 호출해서 객체를 만들기 위해선 
import하거나 하위 패키지 까지 도트 연산자를 이용해 표현해준다

 

 

상속관계: is-a 
포함관계 : has-a

 

 

 

 

다형성

자동형변환이 된 애들만 다시 자식 클래스로 강제 형변환이 가능하다
Whale whale = whale(mammal);

다형성의 기능으로 인해 해당 클래스 객체의 원래 클래스명을 체크하는 것이 
필요한데 이때 사용할 수있는 명령어가 instance of

Parent pc = new Child();
Parent p = new Parent();
System.out.println(p instance of Parent) // --> true;

 

 

 

추상화

클래스가 설계도라면 추상 클래스는 미완성된 설계도이다
abstract 키워드를 사용하여 추상 클래스를 선언할 수 있다

public abstract class 추상클래스명{
}

 

 

추상 클래스는 추상 메서드를 포함할 수 있다
 - 추상 메서드가 없어도 추상 클래스로 선언할 수 있다
추상 클래스는 자식 클래스에 상속되어 자식 클래스에 의해서만 완성될 수 있다
추상 클래스는 여러개의 자식 클래스들에서 공통적인 필드나 메서드를 추출해서 만들 수 있다

public abstract class 추상클래스명{
  abstract 리턴타입 메서드이름(매개변수. ...);  //<<- 구현부 {} 가 없다

상속받은 클래스에서 추상 클래스의 추상 메서드는 반드시 오버라이딩 되어야 함
public class 클래스명 extends 추상클래스명 {
  @Override
  public 리턴타입 메서드이름(매개변수, ...){
  // 실행문
}
}

 

 

 

 

 

interface

public interface 인터페이스명 {

}

 

모든 멤버변수는 public static final이어야 함
-생략 가능
모든 메서드는 public static abstract여야 함
-생략 가능(static메서드와 default 메서드 예외)
생략되는 제어자는 컴파일러가 자동으로 추가해줌

인터페이스는 추상 클래스와 마찬가지로 직접 인스턴스를 생성할 수 없기 때문에 클래스에 구현되어
생성된다
implements키워드를 사용하여 인터페이스를 구현할 수 있다

public class 클래스명 implements 인터페이스명{
  //추상 메서드 오버라이딩
@Override
public 리턴타입 메서드이름(매개변수,...){
  //실행문
}
}

 

 

인터페이스의 추상 메서드는 구현될 때 반드시 오버라이딩 되어야 함
만약 인터페이스의 추상 메서드를 일부만 구현해야 한다면 해당 클래스를 추상 클래스로 변경해주면 됨
(추상 메서드들 중 일부 추상메서드만 구현한다면 해당 클래스를 추상 클래스로 바꿔주고 구현하지 않은 추상 메서드들을 abstract를 통해 다른 클래스에서 구현하도록 떠넘긴다 )

인터페이스간의 상속이 가능하다
인터페이스간의 상속은 implements가 아니라 extends 키워드 사용
인터페이스는 클래스와 다르게 다중 상속이 가능

 

 

 

default 메서드

디폴트 메서드는 추상 메서드의 기본적인 구현을 제공하는 메서드

메서드 앞에 default 키워드를 붙이며 블럭{}이 존재해야한다
default메서드 역시 접근 제어자가 public 이며 생략이 가능함(생략하면 컴파일러가 알아서 자동을 붙여준다)
추상 메서드가 아니기 때문에 인터페이스의 구현체들에서 필수로 재정의 할 필요 없음
(재정의 없이 사용가능한 메서드랄까나...)

 

public class Main implements A {

    @Override
    public void a() {
        System.out.println("A");
    }


    public static void main(String[] args) {
        Main main = new Main();
        main.a();

        // 디폴트 메서드 재정의 없이 바로 사용가능합니다.
        main.aa();
    }
}

interface A {
    void a();
    default void aa() {
        System.out.println("AA");
    }
}

 

 

 

Static 메서드

인터페이스에서 static 메서드 선언이 가능하다
static 특성 그래도 인터페이스의 static 메서드 또한 객체 없이 호출 가능함
선언하는 방법과 호출하는 방법은 클래스의 static 메서드와 동일함
-접근 제어자를 생략하면 컴파일러가 public을 추가해줌

public class Main implements A {

    @Override
    public void a() {
        System.out.println("A");
    }

    public static void main(String[] args) {
        Main main = new Main();
        main.a();
        main.aa();
        System.out.println();

        // static 메서드 aaa() 호출, 인스턴스 생성없이 클래스 이름으로 바로 호출
        A.aaa();
    }
}

interface A {
    void a();
    default void aa() {
        System.out.println("AA");
    }
    static void aaa() {
        System.out.println("static method");
    }
}

 

 

인터페이스 변수 = 구현객체;는 자동으로 타입 변환이 일어납니다.
public class Main {
    public static void main(String[] args) {
        
        // A 인터페이스에 구현체 B 대입
        A a1 = new B();
        
        // A 인터페이스에 구편체 B를 상속받은 C 대입
        A a2 = new C();
        
    }
}

interface A { }
class B implements A {}
class C extends B {}