IT 성장 일기

22.02.08-java_Abstract/Final/Access 본문

IT 학습 노트/Java

22.02.08-java_Abstract/Final/Access

통통배 노아 2022. 2. 8. 23:49

추상(Abstract)

Abstract로 지정되어있는 메소드나 클래스는 직접적으로 사용할 수 없고 반드시 상속해서 사용하도록 강제하는 것이 absract다.

 

아래 예시를 보자.

abstract class A{
	public abstract int b();
    //본체가 있는 메소드는 abstract 키워드를 가질 수 없다.
    public abstract int c(){System.out.println("hello")} --> c는 추상 메소드 임에도 구체적인 로직을
    //가지고 있기 때문에 에러가 발생한다.
    //추상 클래스 내에는 추상 메소드가 아닌 메소드가 존재할 수 있다.
    
    public void d(){
    	System.out.println("world")
    }
}

class B extends A{ //2.대신에 A를 상속받는 B 클래스를 생성.
	public int b(){ //3. 오버라이딩 --->에러 해결
		return 1;
    }
}

public class AbstractDemo{
	public static void main(String[] args){
    	A obj = new A(); //---> 1.에러발생: class A가 abstract이기 때문.
        B obj = new B(); // -->3.하지만 여전히 에러 발생 : 클래스 A가 가지고 있는 메소드 b가 있기때문
        // 추상 메소드를 사용하기 위해서는 반드시 해당 추상 메소드를 오버라이딩 해서 메소드b에 대한 
        //구체적인 로직을 사용하는 쪽에서 정의하여야한다.
        
    }
}

1. 클래스 A를 사용하고자 했지만 추상 클래스라 에러발생

2.따라서 클래스 B를 생성. 이 때 추상 클래스 A를 상속한다. 

3. 추상 A 클래스 안에는 추상 메소드 b가 존재. --> 바로 사용 불가

4. 클래스 B에서 메소드 B에 대해 재정의 (오버라이딩) 하여 사용.

 

Abstract은 상속을 강제하고 있다. 또한  추상 클래스는 구체적인 로직을 담고있지 않고 그 로직을 사용하기 위한 형식(시그니처)만을 가지고 있다.--> 그 시그니처 메소드에 대한 구체적인 구현의 책임은 그것을 사용하는 쪽(클래스 B)에게 넘기고 있다.

 

특징 및 문법

1. abstract 메소드 특징: 일반 메소드와 달리 중괄호롤 끝나지 않고 ( ); 로 끝난다.

2.사실 클래스 A가 추상 클래스라기 보다는 클래스 A가 가지고 있는 메소드가 abstract이라 자동으로 클래스 A도 추상 클래스가 된다. 즉, 멤버 중에 하나라도 abstract라고 하면 이를 담고 있는 클래스도 abstract.

3. 추상 메소드는 구체적인 로직을 가질 수 없다. (에러발생)

4. 추상 클래스 안에는 추상이 아닌 메소드를 가질 수 있다.

 

추상 클래스를 사용하는 이유

추상 클래스는 상속을 강제하기 위한 것이다. 즉 부모 클래스에는 메소드의 시그니처만 정의해놓고 그 메소드의 실제 동작 방법은 이 메소드를 상속 받은 하위 클래스의 책임으로 위임하고 있다.

 

다양한 맥락에서 사용될 수 있는 어떤 기능이 있을 때 그 기능의 공통적인 부분이 있고 사용하는 용도에 따라서 달라질 수 있는 기능들이 있을 때 그것을 추상 클래스로 만들어 이 추상 클래스 (상위 클래스)에는 공통적으로 사용되는 로직을 구현하고 이를 상속 받은 하위 클래스에서는 용도에 따라 달라지는 구현을 사용자가 직접하도록 유도하는 것이 추상클래스를 사용하는 이유이다.

 

 

Final

추상이 상속을 강제하는 것이라면 final은 상속/변경을 금지하는 규제이다.

class Final{
	final int n=100;// 변수의 상수화, final 변수 n
	public void view(final int a) { //메인에서 파이널 지정이 안되는 건 아니지만 관행적으로 부모에 만듦
		
//		n=200; //final 변수는 값의 변경이 불가능
//		a=300; //지역변수 a는 final 변수이기 때문에 변경 불가
		System.out.println(a);
	}
}
class FinalEx extends Final{
//	@Override
//	public void view(final int a) {// final 메서드는 오버라이드 불가
//		
//	}
}

public class FinalTest {

	public static void main(String[] args) {
		Final ob=new Final();
		
		ob.view(200);
	}

특징

1.final 메소드는 오버라이드가 불가하다 (변경 할 수 없기 때문에)

2. final로 지정된 변수 또한 변경이 불가하다.

 

접근 제어자 (Access)

접근 제어자는 클래스의 멤버(변수와 메소드)들의 접근 권한을 지정한다.

 

문법

Class A{
public String y(){
	return "public void y()"
}

private String z(){
	return "public void z()"
}

public String x(){
	return z();
}
}

public class AccessDemo1 {
	public static void main(String[] args){
    	A a=new A();
        System.out.println(a.y());
        System.out.println(a.z()); //-->오류 발생
        System.out.println(a.x());
        
    }
}

위의 예시에서, 메인 함수에서 A의 z 함수를 호출하면 y를 호출할 때 와 다르게 오류가 발생한다.

이는 메소드 z가 private으로 지정되어 있기 때문이다.  private 메소드는 클래스 내부적으로는 사용이 가능하지만 클래스 외부에서는 사용할 수 없다.

반대로 public으로 지정된 메소드는 누구든지 그 클래스의 메소드를 호출해서 사용할 수 있다. 변수도 마찬가지.

 

같은 클래스 소속인 public 메소드 x는 private 메소드 z를 리턴하고 있다. 같은 클래스 내의 public 메소드가 private 메소드를 호출함으로서 외부의 클래스에서 이 private 메소드를 사용할 수 있다. (즉, 외부 클래스에서 private 메소드는 직접적으로 호출이 불가능 하지만 간접적으로 호출이 가능하다)

 

접근 제어자를 사용하는 이유

. 사용자가 사용하도록 의도되어있는 인터페이스들만을 사용할 수 있도록 한다.

 

여러가지 접근 제어자

  같은 class 같은 package 다른 package
서브 클래스
관계없음
public O O O O
protected O O O X
default O O X X
private O X X X