본문 바로가기

프로그래밍/자바

[자바/기본] 인터페이스 Interface + 추상 클래스 Abstract + 다형성 Polymorphism

728x90
반응형
SMALL

인터페이스

  • 자식 클래스가 여러 부모 클래스의 상속을 받을 수 없는 자바의 특성 때문에 다중 상속의 이점을 버리지 않기 위해서 인터페이스를 통해 다중 상속을 지원하고 있음
  • 인터페이스는 추상 메소드 및 상수 만을 포함한다 (추상 클래스는 생성자, 필드, 일반 메소드 포함 가능)
  • 인터페이스 알아야 할 사항
    • 모든 메소드가 public abstract 으로 선언되고 모든 멤버 변수는 public static final로 선언된다.
      • 따라서 위의 modifier들은 생략이 가능하다.
    • 인터페이스를 선언 할 때, interface 라고 선언
    • 상속 하는 클래스에는 implements 사용 (class 상속은 extends)
  • 예제
public interface Testinterface {
    public static final int MIN = 0;
    int MAX = 100; // 생략을 해도 PUBLIC STATIC FINAL 입니다~

    public abstract void testAAA();
    void testBBB(); // public abstract 생략 해도 public
}

interface TestInterface2{
    int MIN = 100;
    void testAAA();
    void testCCC();
}

public class Interface01Main {

	public static void main(String[] args) {
		TestImpl test1 = new TestImpl();
		test1.testAAA();
		test1.testBBB();

		TestImpl2 test2 = new TestImpl2();
		test2.testAAA();
		test2.testBBB();
		test2.testCCC();
		System.out.println(Testinterface.MIN);
		System.out.println(TestInterface2.MIN);
		
		
	} // end main()

} // end class

class TestImpl implements Testinterface{
	@Override
	public void testAAA() {
		System.out.println("AAA");
	}

	@Override
	public void testBBB() {
		System.out.println("BBB");
	}
}

class TestImpl2 implements Testinterface, TestInterface2{

	@Override
	public void testAAA() {
		System.out.println("AAA");
	}

	@Override
	public void testBBB() {
		System.out.println("BBB");
	}

	@Override
	public void testCCC() {
		System.out.println("CCC");
	}
}

추상 클래스

  • 추상 메소드를 가지고 있는 클래스
  • 클래스를 선언 할 때에는 abstract 키워드를 반드시 써 주어야 함
  • 추상 클래스는 인스턴스를 생성 할 수 없음 (new() 불가능)
  • 추상 메소드
    • 원형 (prototype 이라고 함, signature라는 용어도 봤음) 만 선언 되어있고 메소드의 본체가 정의되지 않은 메소드
    • 따라서 {} 부분이 없음
    • 메소드 이름 앞에 반드시 abstract를 사용해주어야함
  • 추상 클래스 사용 목적
    • 추상 클래스를 상속 받는 자식 클래스에서 반드시 구현해야할 메소드가 있을 경우, 그 메소드를 추상 메소드로 만들어서 반드시 override 하는데 목적이 있다.
  • 추상 클래스를 상속 받는 클래스는 반드시 추상메소드를 구현해주어야함
    • {} 를 만들어줘야한다는 이야기임
    • 하지만 상속 받는 클래스 또한 추상일 경우, 추상 메소드를 구현하지 않아도 된다.
  • 예제
public class Abstract01Main {

    public static void main(String[] args) {

       // TestAbstract 클래스의 인스턴스 생성 -> 불가능
       //TestAbstract test1 = new TestAbstract();

       // TestClass 의 인스턴스 생성
       TestClass test2 = new TestClass();
       test2.test = 100;
       System.out.println(test2.testMethod());

       
       TestAbstract test3 = new TestClass();
       test3.test = 999;
       System.out.println(test3.testMethod());
       
    } // end main()

} // end class

// 추상클래스
abstract class TestAbstract {
    int test;

    public int getTest() {return test;}

    // 추상 메소드
    // 수식어 리턴타입 메소드이름(매개변수들, ...);
    public abstract int testMethod();



}


class TestClass extends TestAbstract {
	//상속 받은 메소드 반드시 구현
    @Override
    public int testMethod() {
       return 0;
    }
}

//추상으로 남있는 클래스는 구현 하지 않아도 오케이
abstract class TestClass2 extends TestAbstract{
    int number;
}

다형성

  • 하나의 이름의 클래스나 메소드가 여러가지 형태의 동작을 하는 능력
  • 클래스의 다형성
    • 한 클래스의 타입의 참조 변수로 여러타입의 객체를 참조하는 것이 가능하다.
      • 조상 클래스 타입의 참조 변수로 자손 클래스의 인스턴스를 참조 가능
        • Object a = new Strind("hi"); 이게 된다고 ㅇㅇ
  • 메소드의 다형성
    • 메소드 오버로딩, 메소드 오버라이딩
  • 예제

 

public class Vehicle {
    int speed;

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public void displayInfo() {
        System.out.println("--- Vehicle 정보 ---");
        System.out.println("speed: " + speed);
    }
}

public class Car extends Vehicle{
    int oil;

    public int getOil() {
        return oil;
    }

    public void setOil(int oil) {
        this.oil = oil;
    }

    @Override
    public void displayInfo() {
        System.out.println("--- Car 정보 ---");
        System.out.println("speed: " + getSpeed());
        System.out.println("oil: " + oil);
    }
}

public class HybridCar extends Car {
    int electricity;

    public int getElectricity() {
        return electricity;
    }

    public void setElectricity(int electricity) {
        this.electricity = electricity;
    }

    @Override
    public void displayInfo() {
        System.out.println("--- HybridCar 정보 ---");
        System.out.println("speed: " + getSpeed());
        System.out.println("oil: " + getOil());
        System.out.println("electricity: " + electricity);
    }
}

public class Polymorphism01Main {
	public static void main(String[] args) {

		Vehicle v1 = new Vehicle();
		Car c1 = new Car();
		HybridCar h1 = new HybridCar();

		// 각각의 타입에 오버라이딩 된 메소드가 동작함.
		v1.displayInfo();
		c1.displayInfo();
		h1.displayInfo();

		System.out.println();

		Vehicle car1 = new Car();   // 조상 <- 자손 (가능)
		// 자동차(Car)는 탈것(Vehicle)이다.   Car IS-A Vehicle
		Vehicle car2 = new HybridCar();
		Car car3 = new HybridCar();

		// HybridCar car7 = new Vehicle();  // 자손 <- 조상 (불가)

		// car1~car3 변수 타입에 관계없이
		// 오버라이딩 된 메소드가 '알아서' 동작한다
		car1.displayInfo();
		car2.displayInfo();
		car3.displayInfo();
	} // end main()

}
  • 다형성의 이점 
    • 다형성에 의해서 자식 객체가 부모타입으로 자동 형변환 가능
    • 부모 조상 타입으로 상속된 모든 자손의 타입을 담을 수 있음
    • instance of 연산자 : 형변환이 가능 한지 안한지 true/false 를 반환
      • 주로 상속 관계인지를 확인할 때, 사용됨
  • 다운_업 캐스팅
    • 업캐스팅
      • 자식 클래스의 객체가 부모 클래스 타입으로 형 변환 되는 것
    • 다운 캐스팅
      • 하위 클래스로의 다운캐스팅을 할때, 명시적으로 변환해야하는 타입을 지정해 주어야 하며, 캐스팅에 실패하면 ClassCastException 발생

 

728x90
반응형
LIST