자바 기본 문법 정리(상속과 Interface)
오늘은 기본적인 java의 제어자와 안전한 데이터 접근을 위한 캡슐화 특징
상속과 interface를 통한 코드의 재사용과 용이한 수정에 대하여 전체적으로 다루어 보겠습니다!
이후 Comparable , Comparator를 통한 interface 정렬 방식에 대해서도 자세히 정리해 보도록 하겠습니다.
1. modifier(제어자)
-접근 제어자 : 접근 권한 지정
접근제어자 Class 클래스명{
접근제어자 인스턴스 변수
접근제어자 인스턴스 메소드
access modifier public protected 생략(default) private
usage modifier abstract static final
Class Person{
Private Int age;
Public void setAge(int age){
This age = age;}
- access modifier : 클래스, 메서드, 속성에 대한 접근을 제한한다.
- public : 접근 제한이 전혀 없다.
- protected : 상속 관계에서는 제한이 없다. 상속 관계가 아니면 같은 package가 아닌 경우 접근 불가
- 생략(default): 같은 package가 아닌 경우 접근 불가
- usage modifier : 클래스, 메서드, 속성의 기능을 제한한다.
- private : 선언한 클래스 내에서만 접근 가능 * private 는 public 메소드인 setter getter 을 통해서 안전하게 검증 하여 사용 가능 * 주요 데이터는 은닉하고 접근을 함수로만 할 수 있도록!!! * privat은 상속 관계라도 접근 불가 (캡슐화)
package chapter;
public class MyDate {
private int year;
String name;
public int getYear() {
return year;
}
public void setYear(int year) {
if(year<2024) {
System.out.println("2024년 이후로 설정해 주세요");
}
this.year = year;
}
2. Encapsulation(캡슐화)
: 대부분의 속성과 일부 메소드를 private , default(생략) , protected 를 이용해서 캡슐로 쌓는 기능
- 관련이 있는 변수와 함수를 하나의 클래스로 묶고 외부에서 쉽게 접근하지 못하도록 은닉
- 객체에 직접적인 접근을 막고 => 객체가 제공하는 필드와 메소드를 통해서만 접근
- 보호
- 은닉 ==> decouple 효과 및 수정성을 높이는
3. 상속
: 부모(super class)로 부터 자산(속성, 메서드..)를 물려 받기
자식 클래스는 부모 클래스를 선택해서, 그 부모의 멤버를 상속
형식
* [modifiers] class ClassName [extends 부모클래스이름]{
- 코드 재사용
- 단일 상속만 가능 =>클래스로 부터
- 생성자는 상속 대상에서 제외
어떨 때 상속을 사용하고 어떨때 클래스 만들고 객체 생성으로 사용하는가?
- 있는 그대로 쓸 때 객체 생성(재사용)으로 이용!
- 수정이 필요할 때 상속(재사용 +수정) 으로 활용!
*상속 예시
public class Customer { //부모 클래스
private String name;
private int age;
private String address;
public Customer() {
this("UPlus", 2, "서울 강남구 선릉로" );
}
public Customer(String name, int age, String address) {
this.name = name;
this.age = age;
this.address =address;
}
public class MainCustomer extends Customer { //자식 클래스
private String hobby;
public MainCustomer() {
super();
}
public MainCustomer(String name, int age, String address, String hobby) {
// this.name =name; // privat은 상속 관계라도 접근 불가
setName(name); //선언하지 않았지만 상속 받았기 때문에 호출 가능
setAddress(address);
setAge(age);
this.hobby=hobby; //자신의 인자는 접근 가능
* super 속성
- 생성자는 상속 되지 않지만 호출을 통해 코드를 재사용할 수있다.
- super(~)
- 주의점 : 생성자 호출은 생성자의 첫번째 명령에서만 호출할 수 있다.
- 재정의에 의해 무시된 상속 받은 멤버(메서드, 속성)를 호출할 때 super를 통해 접근
- super.메서드이름(~) super.속성
3-1. Method Override(메서드 재정의)
: 상속은 수정이 목적이기 때문에 오버라이드를 하기 위해 사용합니다.
- 상속 받은 메서드와 동일한 이름의 메서드를 선언.
상속 받은 메서드와 전체적인 기능을 동일하지만 상세 구현이 조금 다를 경우
기존의 상속 받은 메서드로 사용할 수 없으므로 새로운 메서드를 추가로 선언해야 한다.
이때 상속 받은 메서드와 이름, 인자, 리턴타입을 동일하게 선언한다.
- 효과
상속 받은 메서드와 이름, 인자가 같으므로 메서드 호출 방법이 기존의 코드와 동일하고
리턴타입이 동일하므로 호출 후 처리 방법이 기존의 코드와 동일하므로
기존의 코드를 수정하지 않고 변경된 내용을 반영할 수 있다.
- 규칙
메서드 이름, 인자, 리턴타입이 같아야 한다.
*@Override
class Animal { // 부모 클래스에서 메서드 정의
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {// 자식 클래스
@Override // 부모 클래스의 메서드를 오버라이드 (재정의)
public void sound() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Dog.d1 = new dog();
d1.sound();
}
}
: 결과 값은 수정 된 "Dog barks" 출력
* toString 을 통하여 Override 호출도 가능
@Override //override 규칙대로 팜수를 정의하지 않으면 compile error 발생
public String toString() {
StringBuilder builder = new StringBuilder(super.toString());
builder.append(",hobby=").append(hobby)
.append("]");
return builder.toString();
4. interface
- 다중 상속과 추상 메서드 집합
상속의 경우 단일 상속만 가능
-다중 상속에 이점을 활용하기 위하여 구현된 메소드 없이 추상 메소드로만 구성
*추상 메소드 ; 메서드의 선언부만 작성하고 구현을 하지 않음
-상속 및 추상 메서드 강제 구현 외에도, 다양한 프레임워크에서 클래스끼리 통신하는데 자주 사용
부모에서 구현되지 않은 해당 부분은 자식에서 구현을 진행 해야한다.
상속의 경우 오바라이드는 옵션으로 tostring으로 호출 가능했지만,
interface 추상 메서드를 반드시 Overried 하도록 위임 필요!!
✅ 상수와 추상 메서드로만 구성
=> 딱히 선언하지 않아도 속성은 public static final로 선언이 되고
메서드는 public abstract(추상 메소드)으로 선언된다.
✅ 다중 상속
=> 다형성을 위해 다중 상속이 된다.
✅추상 메서드
- sub class(상속 받는 클래스, 자식 클래스)에서 추상 메서드를 반드시 Override 하도록 위임
=> sub class에서 추상 메서드를 Override하지 않으면 컴파일 에러 발생 한다.
[선언]
[public] interface 인터페이스명 [extends super인터페이스명1, ....]{ }
[구현]
[modifiers] class 클래스명 [extends super클래스]
[implements super인터페이스명1, ....]{}
*구현 : implements // 정의 되지 않은 부분 implements에서 구현
interface Flyer extends Cloneable{ //interface 간에 상속은 extends
int type =1; // public static final 로 선언
void fly(); // public abstract로 선언됨.
}
class Human{
String name;
public void start() {
System.out.println("걸어 봅시다.");
}
}
class SuperMan extends Human implements Flyer{
public SuperMan(String name) {
this.name = name;
}
public void fly() {
System.out.println("하늘을 날아서 지구를 구해야지");
}
public void stop() {
System.out.println("그만 움직이고 쉬어야징!!");
}
}