
1. 액세스 제어
자유와 규제
너무 자유롭다면 소통이 어려워지므로 적절한 규제가 필요하다.
규정에는 액세스 수정자, 추상 클래스, 최종 및 인터페이스가 포함됩니다.
문법
액세스 수정자
개체에서 멤버(변수, 메서드)를 사용할 때의 권한
// public이 접근 제어자
public String x(){
return "public";
}
// private이 접근 제어자
private String y(){
return "private";
}
사용 이유
보안이나 논리상의 이유로 사용자 즉, 외부로부터의 접근을 규제함으로써 오작동 발생을 줄일 수 있기 때문이다.
미세 제어
| 공공의 | 보호 | 기본 | 사적인 | |
| 같은 패키지 같은 반 |
영형 | 영형 | 영형 | 영형 |
| 같은 패키지 상속 관계 |
영형 | 영형 | 영형 | 엑스 |
| 같은 패키지 상속 X |
영형 | 영형 | 영형 | 엑스 |
| 다른 패키지 계승 |
영형 | 영형 | 엑스 | 엑스 |
| 다른 패키지 상속 X |
영형 | 엑스 | 엑스 | 엑스 |
기본적으로 공개 및 비공개를 알고 있으므로 나중에 보호 및 기본을 사용할 수 있습니다.
- 같은 클래스의 경우 접근 수식어와 상관없이 사용 가능
- 동일한 패키지 내에서 private만 사용할 수 없습니다.
- 다른 패키지의 경우 public만 가능하지만 다른 패키지의 하위 클래스가 상속되면 보호도 가능합니다.
- public은 어디에서나 접근 가능, private는 같은 클래스 내에서만 사용 가능
클래스 액세스 한정자
- 기본값은 액세스 한정자가 첨부되지 않은 경우이며 동일한 패키지에서만 사용할 수 있습니다.
- public은 다른 패키지의 클래스에서 사용할 수 있습니다.
공개 클래스 이름과 파일 이름이 동일해야 합니다.
PublicNameDemo.java
package org.opentutorials.javatutorials.accessmodifier.inner;
//public class PublicName {} <ㅡ 에러 발생
public class PublicNameDemo {}
하나의 소스 코드에는 하나의 공용 클래스만 존재할 수 있기 때문입니다.
2. 초록
문법
추상은 한국어로 ‘추상’을 의미합니다.
추상 클래스를 사용하려면 상속해야 합니다. 규제한다고 볼 수 있습니다.
abstract class A{
public abstract int b();
public void d(){
System.out.println("world");
}
}
// 추상 클래스 A를 오버라이딩
class B extends A{
public int b(){return 1;}
}
public class AbstractDemo {
public static void main(String() args) {
// A obj = new A(); <ㅡ 에러 발생
B obj = new B();
System.out.println(obj.b());
}
}
- 추상 메서드에는 본문이 없어야 합니다. 즉, 중괄호 안에 내용이 없어야 합니다.
- 멤버 중 하나라도 추상이면 클래스는 추상입니다.
사용 이유
공통 부분은 추상 클래스를 사용하여 대략적으로 정의됩니다.
상황에 따라 변경되는 유연한 부분은 사용할 때마다 변경할 수 있도록 하는 것입니다.
// ex)
abstract class robot{
public void attack(){}
}
class punchRobot extends robot{
public void attack(){
System.out.print("punch");
}
}
class missileRobot entends robot{
public void attack(){
System.out.print("missile");
}
}
디자인 패턴
추상화를 사용하여 템플릿을 결정한 후 하위 클래스에 책임을 위임하는 패턴입니다. 템플릿 메서드 패턴그것은 말한다.
이 반복되는 패턴은 디자인 패턴오전.
장점
- 좋은 디자인은 단기간에 배울 수 있습니다.
- 의사소통에 도움이 됩니다.
3. 최종
상속 또는 변경 금지 규정
첫 번째 정의 이후에는 변경할 수 없습니다.
// final 필드: 값 변경 불가
static final double PI = 3.14;
// final 메소드: 상속 불가
class A{
final void a(){}
}
// final 클래스: 상속 불가
final class b{
final void b(){}
}
4. 인터페이스
문법과 개념
인터페이스를 사용하는 개체는 인터페이스의 메서드를 구현해야 합니다.
interface I{
public void z();
}
class A implements I{
public void z(){}
}
위의 코드에서 클래스 A는 인터페이스 I을 “구현”합니다.
사용 이유
인터페이스는 클래스에 대한 사양 역할을 합니다.
인터페이스를 사용하는 클래스는 사양을 지정하여 사용할 수 있습니다.
// 인터페이스
public interface Calculatable {
public void setOprands(int first, int second, int third) ;
public int sum();
public int avg();
}
// 인터페이스를 구현한 클래스
class CalculatorDummy implements Calculatable{
public void setOprands(int first, int second, int third){
}
public int sum(){
return 60;
}
public int avg(){
return 20;
}
}
메인 클래스
public class CalculatorConsumer {
public static void main(String() args) {
CalculatorDummy c = new CalculatorDummy();
c.setOprands(10, 20, 30);
System.out.println(c.sum()+c.avg());
}
}
규칙
하나의 클래스는 여러 인터페이스를 구현할 수 있습니다.
interface I1{
public void x();
}
interface I2{
public void z();
}
class A implements I1, I2{
public void x(){}
public void z(){}
}
인터페이스도 상속됩니다.
interface I3{
public void x();
}
interface I4 extends I3{
public void z();
}
class B implements I4{
public void x(){}
public void z(){}
}
인터페이스의 멤버는 public이어야 합니다.
인터페이스를 사용하는 다른 클래스가 액세스할 수 있도록 공용이어야 합니다.
추상 VS 인터페이스
- 추상 클래스는 일반 클래스이므로 구체적인 논리 또는 상태를 가질 수 있습니다.
- 인터페이스는 구체적인 논리나 상태를 가질 수 없습니다.
5. 다형성
메소드 오버로딩과 다형성
다형성
하나의 메서드나 클래스가 있으면 서로 다른 방식으로 작동합니다.
예) 과부하
클래스와 다형성
class A{
public String x(){return "x";}
}
class B extends A{
public String y(){return "y";}
}
public class PolymorphismDemo1 {
public static void main(String() args) {
A obj = new B();
obj.x();
obj.y(); // 에러 발생
}
}
위 코드는 obj 인스턴스의 타입인 A 클래스의 y 메소드가 존재하지 않기 때문에 에러가 발생합니다.
메서드 x가 자식 클래스인 B 클래스에 오버로드되어도 오류가 발생하지 않습니다.
- 부모 타입으로 자식 인스턴스가 생성되고 자식 메서드가 부모 메서드를 오버로드하면 자식 메서드가 더 높은 우선 순위를 갖습니다.
- 타입이 부모이므로 자식 클래스에만 존재하는 메서드는 사용할 수 없습니다.
인터페이스와 다형성
public class CalculatorDemo {
public static void execute(Calculator cal){
System.out.println("실행결과");
cal.run();
}
public static void main(String() args) {
Calculator c1 = new CalculatorDecoPlus();
c1.setOprands(10, 20);
Calculator c2 = new CalculatorDecoMinus();
c2.setOprands(10, 20);
execute(c1);
execute(c2);
}
}
- c1과 c2는 데이터 유형이 같지만 인스턴스가 다르기 때문에 기능이 다릅니다.
- 인스턴스와 동일한 데이터 타입으로 생성할 경우 각 타입별로 execute 메소드를 생성해야 하므로 코드 중복이 발생한다.
interface I2{
public String A();
}
interface I3{
public String B();
}
class D implements I2, I3{
public String A(){
return "A";
}
public String B(){
return "B";
}
}
public class PolymorphismDemo3 {
public static void main(String() args) {
D obj = new D();
I2 objI2 = new D();
I3 objI3 = new D();
obj.A();
obj.B();
objI2.A();
//objI2.B();
//objI3.A();
objI3.B();
}
}
- 클래스가 인터페이스를 구현하는 경우 클래스 유형은 구현 인터페이스 유형이 될 수 있습니다.
- objI2의 타입이 인터페이스 I이므로 I에 대한 메소드가 존재하지 않아 오류가 발생한다. ojbI3.A()의 오류 발생 원인도 이와 같다.