[TIL] PowerJava chap7 - 추상 클래스, 인터페이스, 중첩 클래스

은동·2023년 2월 2일
0

JAVA_TIL

목록 보기
7/8
post-thumbnail

✔️ 추상 클래스 (abstract class)

완전하게 구현되어 있지 않는 메소드를 가지고 있는 클래스를 의미
추상 클래스로는 객체 생성 불가
하나 이상의 추상 메소드(몸체가 없는 메소드) 필요
추상 메소드만 가져야 하는 것은 아님
추상 클래스를 상속받는 클래스에서는 반드시 추상 메소드를 재정의하여야 함

public abstract class Animal{
	public abstract void move(); //세미콜론으로 종료됨
    }
}

public clas Lion extends Animal{
	public void move() {
		System.out.println("사자의 move()메소드 입니다")
        }
}        
  • 용도
    부모 클래스의 메소드가 자식 클래스에서 오버라이드되었는지 체크용
    일반 메소드로 정의되면 자식 클래스에서 오버라이드하지 않아도 컴파일러가 확인할 방법이 없음

  • 언제 사용?
    관련된 클래스들 사이에서 코드를 공유할 때 사용
    공통적인 필드나 메소드의 수가 많은 경우, 또는 public 이외의 접근 지정자를 사용해야 하는 경우에 사용
    정적이 아닌 필드나 상수가 아닌 필드를 선언하기 원할 때 사용


✔️ 인터페이스 (interface)

여러 프로그래머들이 독립적으로 클래스를 작성하고 이 클래스들을 합쳐서 하나의 소프트웨어를 완성하는 상황에서 각자의 클래스를 다른 사람의 클래스와 연결하려면 클래스 간의 상호작용을 기술하는 일종의 규격이 있어야 하는데, 이러한 규격을 인터페이스라고 함

자바의 다형성을 극대화하여 개발코드 수정을 줄이고 프로그램 유지보수성을 높이기 위해 인터페이스를 사용한다.

  • 구현
    interface 키워드를 통해 선언하고, implements 키워드를 통해 일반 클래스에서 인터페이스를 구현
public interface 인터페이스_이름{
	//상수 
    타입 상수명 =;
    
    //추상 메소드
    타입 메소트명(매개변수, ...);
    
    //디폴트 메소드
    default 타입 메소드명(매개변수, ...){
		//구현부
    }
    
    //정적 메소드
    static 타입 메소드명 (매개변수){
		//구현부
	}
}

class 클래스_이름 implements 인터페이스_이름 {...}

상수 : 인터페이스에서 제공해주는 값만 참조해라
추상 메소드 : 추상 메소드를 오버라이딩해서 재구현해라
디폴트 메소드 : 인터페이스에서 제공해주지만, 맘에 안 들면 각자 구현해서 써라
정적 메소드 : 인터페이스에서 제공해주는 것으로 무조건 사용

참고 : https://limkydev.tistory.com/197

+) 인터페이스 안에서 선언되는 메소드들은 모두 묵시적으로 public abstract임 따라서 수식어는 없어도 됨

  • 언제 사용?
    관련 없는 클래스들이 동일한 동작을 구현하기를 원할 때 사용
    특정한 자료형의 동작을 지정하고 싶지만 누가 구현하든지 신경쓸 필요 없을 때 사용
    다중 상속이 필요할 때 사용(여러 개의 인터페이스 동시 구현)

  • 인터페이스와 타입
    인터페이스의 이름은 클래스의 이름과 마찬가지로 참조 변수를 정의하는데 사용될 수 있음
    인터페이스를 자료형처럼 사용하여서 참조 변수를 정의하면, 이 인터페이스를 구현한 객체라면 어떤 것이라도 이 참조 변수에 대입할 수 있음


✔️ 인터페이스 다중 상속

  • 인터페이스끼리의 상속
    extends 키워드 사용
public interface RemoteControl{
	public void turnOn();
    public void turnOff():
}    

// 여기에 메소드를 추가해버리면 (예를 들어 볼륨을 조절하는) 
// 이 인터페이스를 구현하였던 모든 클래스가 동작하지 않음
// 그래서 인터페이스끼리 상속을 받아서 확장시킴

public interface AdvancedRemoteControl extends RemoteControl{
	public void volumeUp();
    public void volumeDown();
}    
  1. 여러 개의 인터페이스 동시 구현
interface Drivable {void drive();}
interface Flyable {void fly();}

public class FlyingCar1 implements Drivable, Flyable{
	public void drive() {System.out.println("I'm driving.");}
	public void fly()	{System.out.println("I'm flying");}

	public static void main(String[] args) {
		FlyingCar1 obj = new FlyingCar1();
		obj.drive();
		obj.fly();

	}

}
  1. 하나의 클래스를 상속받고 또 하나의 인터페이스 구현
interface Flyable2 {void fly();}

class Car {
	int speed;

	public void setSpeed(int speed) {
		this.speed = speed;
	}
	
}
public class FlyingCar2 extends Car implements Flyable2 {
	public void fly() {System.out.println("I'm Flying.");}

	public static void main(String[] args) {
		FlyingCar2 obj = new FlyingCar2();
		obj.setSpeed(60);
		obj.fly();
	}

}

✔️ 인터페이스 상수 정의

인터페이스에서 정의된 변수는 자동적으로 public static final이 됨

public interface MyConstants {
	int NORTH = 1;
   	int EAST = 2;
    int WERT = 3;
    int SOUTH = 4;
}    

만약 클래스가 MyConstants 인터페이스를 구현한다면 단순히 NORTH라고 써주어도 된다


✔️ 디폴트 메소드

JAVA 7 까지는 추상메소드와 상수만 사용 가능했던 반면, JAVA 8 부터는 디폴트 메소드와 정적 메소드를 사용 가능

인터페이스 개발자가 메소드의 디폴트 구현을 제공할 수 있는 기능
디폴트 메소드가 정의되어 있으면 인터페이스를 구현하는 클래스가 메소드의 몸체를 구현하지 않아도 메소드 호출 가능

메소드 앞에 default키워드를 붙임

인터페이스가 기존의 코드를 건드리지 않고 확장될 수 있도록 하기 위해 사용됨(인터페이스에 의해 정의된 메소드는 클래스에 의해서 반드시 구현되어야 하기 때문)

interface MyInterface{
	public void myMethod1();
	
	default void myMethod2() {
		System.out.println("myMethod2()");
	}
}
public class DefaultMethodTest implements MyInterface {
	public void myMethod1()	{
		System.out.println("myMethod1()");
	}
	
	public static void main(String[] args) {
		DefaultMethodTest obj = new DefaultMethodTest();
		obj.myMethod1();
		obj.myMethod2();

	}
}

✔️ 정적 메소드

클래스의 객체에 들어 있는 것이 아니라 클래스에 들어있음
메소드 앞에 static 키워드를 붙이면 됨

interface MyInterface{
	static void print(String msg) {
    	System.out.println(msg + " : 인터페이스의 정적 메소드 호출");
    } 
}   
public class StaticMethodTest{
	public static void main(String[] args){
		MyInterface.print("java 8");
    }
}

✔️ 중첩 클래스

클래스 안의 클래스
내부에 클래스를 가지고 있는 클래스를 외부 클래스(outer class)
클래스 내부에 포함되는 클래스를 중첩 클래스(nested class)

class OuterClass{
	...
    
    class NestedClass{
		...
	}
}    

✔️ 중첩 클래스의 종류

  1. 정적 중첩 클래스 : 앞에 static이 붙어서 내장되는 클래스

  2. 비정적 중첩 클래스 : static이 붙지 않은 일반적인 중첩 클래스
    - 내부 클래스 : 클래스의 멤버처럼 선언되는 중첩 클래스
    - 지역 클래스 : 메소드의 몸체 안에서 선언되는 중첩 클래스
    - 익명 클래스 : 수식의 중간에서 선언되고 바로 객체화되는 클래스


✔️ 내부 클래스(inner class)

내부 클래스의 접근 지정자는 public, private, protected or package(default)
내부 클래스는 외부 클래스의 인스턴스 변수와 메소드를 전부 사용할 수 있음(private도 가능)

class OuterClass{
	private int value =10;
	
	class InnerClass{
		public void myMethod() {
			System.out.println("외부 클래스의 private 변수 값: "+value);	
            //private 참조 가능
		}
	}
	OuterClass(){
		InnerClass obj = new InnerClass();
		obj.myMethod();
	}
}
public class InnerCaseTest {

	public static void main(String[] args) {
		OuterClass outer = new OuterClass();
	}

}

-> 외부 클래스의 생성자에서 내부 클래스의 객체를 생성
만약 외부 클래스의 바깥에서 내부 클래스의 객체를 생성하려면 아래와 같이 생성하여야 함

OuterClass outer = new OuterClass();
OUterClass.InnerClass inner = outer.new InnerClass();

내부 클래스도 외부 클래스의 인스턴스 멤버이다. 따라서 외부 클래스 객체가 만들어져야 내부 클래스도 만들 수 있다.


✔️ 지역 클래스 (local class)

메소드 안에 정의되는 클래스
접근 제어 지정자를 가질 수 없음
abstract 또는 final로만 지정 가능
지역 클래스는 메소드 안에서만 사용이 가능

class LocalInner {
	private int data=30;
	
	void display() {
		final String msg = "현재의 데이터 값은 ";
		
		class Local {
			void printMsg() {
				System.out.println(msg+data); //private 변수 접근 가능
			}
		}
		Local obj = new Local();
		obj.printMsg();
	}
}
public class LocalInnerTest {

	public static void main(String[] args) {
		LocalInner obj = new LocalInner();
		obj.display();

	}

}

지역 클래스는 외부 클래스의 인스턴스 변수뿐만 아니라 메소드의 지역 변수(반드시 final)에도 접근 가능(지역 클래스의 인스턴스가 메소드 호출보다 더 오랜 기간 동안 존재할 수 있기 때문)

  • 중첩 클래스를 왜 사용할까?
    내부 클래스는 외부 클래스의 private멤버도 접근 가능하기 때문

✔️ 익명 클래스

클래스 몸체는 정의되지만 이름이 없는 클래스
익명 클래스는 클래스를 정의하면서 동시에 객체를 생성
이름이 없기 때문에 한 번만 사용 가능
하나의 객체만 생성하면 되는 경우에 사용

상속 받고자 하는 부모 클래스의 이름이나 구현하고자 하는 인터페이스의 이름을 적어줌

// 이름이 있는 클래스의 경우
class Car extends Vehicle{
	...
}
Car obj = new Car();

// 익명 클래스의 경우 
Vehicle obj = new Vehicle(){
	...
};
// 인터페이스를 구현하는 익명 클래스
interface RemoteControl2{
	void turnOn();
	void turnOff();
}
public class AnonymousClassTest {

	public static void main(String[] args) {
		RemoteControl2 ac = new RemoteControl2() {
			public void turnOn(){
				System.out.println("tv turnOn()");
			}
			public void turnOff() {
				System.out.println("tv turnOff()");
			}
		};
		ac.turnOn();
		ac.turnOff();
	}

}
profile
자자 선수입장~

0개의 댓글