상속
부모 클래스를 자식클래스가 상속받을 때는 extends를 사용한다.
public class 자식클래스 extends 부모클래스{
}
자식클래스가 부모클래스를 상속받으면 생성자에서 부모의 기본 생성자를 부르는 코드를 자동으로 생성해준다.
public 자식클래스(){
super();
}
이때 부모에 기본생성자가 없으면 에러가 발생하기 때문에 매개변수까지 넣어서 딱 불러주면 오류 없어진다. 부모에서 private로 선언된건 접근할 수 없지만 상속은 받는다. 부모에서 선언된 애들은 자식의 참조변수를 통해 필드와 메소드로 접근가능하다.
메소드 재정의(= 메소드 오버라이딩)
--> 다형성을 위해서
오버라이딩 규칙
1. 부모 메소드의 선언부와 동일해야 한다.
2. 접근 제한을 더 강하게 오버라이딩할 수 없다.
(private -> public 으로 변경은 가능하지만 public -> private로의 변경은 불가능하다.)
3. 새로운 예외를 throws할 수 없다. (나중에...)
SOLID(객체지향설계)
● SRP(단일책임의 원칙) - 한가지 일만 하도록 하는 것
● OCP(개방 폐쇄의 원칙) - 재사용 -> 요구사항의 변경이나 추가사항이 발생해도 코드 수정이 일어나지 말아야한다.
--> 상속을 기반으로 한다.
● DIP(의존성 역전의 원칙) --> 오버라이딩을 통해 부모변수를 통해 자식의 확장된 메소드로 접근가능하다.
--> OCP + DIP (상속, 추상, 다형성)
-->객체지향설계를 하려면 실행부 main함수 부분만 수정해주면 된다.나머지부분은 바뀌지 않고 실행되어야 구현된것이다.
아래 코드는 부모클래스를 통해 일반화한 자식클래스들을 List에 넣어서 관리하는 일반화 코드이다.
public class 집 {
List<동물> 애완동물들 = new ArrayList<동물>();
void 애완동물추가(동물 애완동물) {
애완동물들.add(애완동물);
}
void 애완동물출력() {
for(동물 애완동물 : 애완동물들) {
System.out.println("애완동물 이름 = "+애완동물.getName());
}
}
}
바뀔 수 있는 실행코드부분으로 집에 대한 클래스를 여러번, 마음껏 사용해준다.
public class 실행 {
public static void main(String[] args) {
집 나의집 = new 집();
나의집.애완동물추가(new 강아지("몽실이"));
나의집.애완동물추가(new 고양이("나비야"));
나의집.애완동물추가(new 고양이("악돌이"));
나의집.애완동물출력();
}
}
클래스 = 속성 + 동작(메소드)
명사는 클래스이름이나 속성명이 된다.
동작은 메소드가 된다.
일반화 vs 특별화
일반화: 변경되지 않는 코드! --> 부모클래스
특별화 : 한가지 기능만 하도록 명시적으로 고정된 코드 --> 자식클래스
부모-자식클래스에서 객체를 일반화하면
부모 변수 = new 자식();
직사각형이 정사각형이 될 수 있지만 정사각형은 직사각형이 될 수 없음을 기억하자!
오버로딩
동일한 클래스 내에서 함수명을 동일하게 하면서 리턴타입과 매개변수만 다르게 해서 선언하는 것
오버라이딩
부모자식관계에서 함수명을 아예 똑같이 해서 부모메소드에서 정의한 기능을 확장, 변경 하는 것이다.
부모 변수 = new 자식()
이렇게 하면 부모객체만 접근할 수 있지만 부모 객체를 자식 객체에서 메소드 오버라이딩한게 있다면 부모의 메소드를 불러도 오버라이딩된 자식의 메소드를 불러오게 된다.
추상클래스
추상클래스는 new를 통해 객체를 만들수 없고 변수만 선언할 수 있다. 클래스 안에 내용 중에 함수가 정의되지 않은 추상메소드가 있다면 그 클래스는 추상클래스가 된다. 추상 메소드가 없어도 추상클래스로 선언할 수 있다.
목적--> 부모의 참조변수를 통해서 자식의 메소드에 접근하려고 할 때 사용한다. 그냥 클래스로도 사용할 수 있지만 부모클래스에서 사용되지도 않는 메소드를 선언해서 메소드영역의 메모리를 차지하게 된다. 비효율적이므로 abstract를 통해 함수의 원형만 선언해준다. 이러면 메모리영역에 들어가지 않는다.???
추상클래스를 통한 오버라이딩의 목적
1. 객체를 만들면 안될 경우의 논리오류를 구문오류로 바꿔줄수 있다.
2. 부모 변수를 통해 자식의 메소드를 호출할 수 있다.
Override 어노테이션 사용
@Override를 재정의된 메소드 안에서 사용해주면 부모클래스의 함수명을 확인하고 자식클래스에서 함수명을 동일하게 정의해주었는지를 확인해서 혹시 모를 논리오류를 구문오류로 바꿔줄 수 있다.
main이나 함수 안에 있는 애들만 stack에 넣어준다.
위의 집과 실행에 대한 JVM 메모리 영역
final 클래스
더이상 상속될 수 없는클래스이다.
public final class 클래스{
}
final 메소드
오버라이딩할 수 없는 메소드가 된다.-> 자식클래스에서 재정의할 수 없다.
public final 리턴타입 메소드(매개변수,....){
}
protected 접근 제한자
상속된 클래스와 동일한 패키지에서 이 클래스를 사용할 수 있다. 생성자, 메소드에 접근 가능하다. 단, new 연산자를 사용해서 생성자를 직접 호출할 수는 없다. super()로 생성자를 호출할 수 있다.
package ch07.sec06.package1;
public class A{
protected String field;
protected A(){
}
protected void method(){
}
}
package ch07.sec06.package2;
public class D extends A{
public D(){
super();//상속을 이유로 부모생성자를 불러올 수 있다.
}
public void method1(){
this.field = "value";//상속은 받았기 때문에 필드들에 접근 가능
this.method();
}
public void method2(){
A a = new A();//객체 생성은 안됨, A클래스와 다른 패키지 안에 있는것이라서
a.field = "value";
a.method();
}
}
'JAVA공부(이것이 자바다)' 카테고리의 다른 글
인터페이스 이어서 (0) | 2023.06.02 |
---|---|
상속 이어서 (0) | 2023.05.31 |
클래스 이어서 (0) | 2023.05.29 |
java참조타입 이어서 (0) | 2023.05.26 |
java의 참조타입 (0) | 2023.05.25 |