상속
상속은 기존에 존재하는 클래스를 물려받아 이용하는것이며, 작성해야 할 코드의 양이 줄어드는 효과가 있다.
class 상속받을 클래스명 extends 상속할 클래스명 { }
class Parents{ }
class Child extends Parents { } // Child 클래스로 Parents 클래스 상속
상속을 받은 클래스는 부모 클래스의 변수와 함수를 가질수 있다.
class Parents{ void sayHello() {System.out.println("안녕하세요");} }
class Child extends Parents { }
public class test { public static void main(String[] args) { Child c = new Child(); c.sayHello(); } }
// "안녕하세요" 출력
오버라이딩
부모 클래스로부터 상속받은 메서드를 다시 작성할때 사용한다. 리모델링과 비슷하다.
class student { void eat() { System.out.println("밥먹기");} void say() { System.out.println("안녕하세요"); }}
class leader extends student { void say() { System.out.println("차렷 경례"); } }
public class test { public static void main(String[] args) { {leader l = new leader(); l.eat(); l.say(); }} }
// "밥먹기" "차렷 경례" 출력
기존 부모인 student 클래스에 있던 say() 메서드를 leader 클래스 안에서 오버라이딩 했다.
this : 객체에서 메서드를 호출할 때, 메서드는 공용으로 사용하게 되는데 이때 각 인스턴스를 저장하는 변수를 this라고 한다 ( = 해당 클래스의 객체)
상속과 생성자
부모 클래스가 자식에게 상속을 한 후, 퍼블릭 클래스의 메인에서 자식의 주소를 가져와서 부모에 있는 변수나 메서드를 호출하면 부모는 따로 생성하지 않아도 호출이 가능한데, 이것은 자식 클래스 안에 기본 생성자 super()에 의해 자식 클래스가 생성될 때, 부모 클래스가 super()에 의해 초기화 되기 때문이다.
class Parents{int a = 10;}
class Child extends Parents{ Child() {super();} } // Child() {super()} 기본생성자 자동생성
Child c = new Child(); // 자식 클래스 생성, 초기화
System.out.println(c.a); // 출력값 10 Child 기본생성자 super에 의해 Parents가 초기화되어 호출가능
만약에 부모 클래스에 기본생성자가 아닌 매개변수를 가진 생성자를 만들었다면, 기본생성자는 자동으로 생성되지 않기 때문에 수동으로 기본생성자를 만들어주거나, 자식 클래스에서 super(매개변수);의 형태로 만들어 줘야한다.
패키지는 자바클래스를 여러개 묶어놓은것으로, 클래스의 유지보수 및 관리를 용이하게 한다.
import는 다른 패키지에 있는 클래스를 사용하고 싶을 때 참조목적으로 사용한다.
예시)
java.util.Scanner sc = new java.util.Scanner(System.in); // 스캐너 경로를 모두 적어야한다.
import java.util.Scanner;
Scanner sc = new Scanner(System.in); // import로 경로를 참조하여 비교적 코드가 간단해진다.
또한 import는 다른 패키지에 있는 클래스를 참조할때도 사용할수 있는데
이때는 import 패키지이름.클래스이름; 을 상단에 적고
클래스이름.변수 또는 함수의 이름을 적는다.
이때 변수 또는 함수는 public 타입이여야 한다.
import package1.test; // import로 package1의 test클래스 참조
System.out.println(test.a); // test 클래스 안의 public 변수 a 출력
접근 제어자
public | 접근 제한 없음 | 주로 사용 |
protected | 같은 패키지 내와 자손 클래스에서 접근가능 | |
default | 같은 패키지에서만 접근가능 | 제어자를 생략했을때 기본적용 |
private | 같은 클래스 내에서만 접근가능 | 주로 사용 |
보통 접근 제어자를 사용하는 경우에는 퍼블릭과 프라이빗을 많이 쓰고, 디폴트는 기본적으로 적용되어있다.
접근제어자는 class의 자식인 변수와 함수에 적용된다.
private의 경우에는 같은 클래스 내에서만 접근을 허용하기 때문에 코드의 보안을 목적으로 쓰이며,
getter와 setter를 통해서만 접근을 허용한다.
getter와 setter는 getAbc(), setAbc()의 의 형태로 생성되며, get과 set 뒤에 오는 변수 이름의 첫 글자는 대문자가 된다.
private String name;
Private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name }
위와 같은 형태로만 외부에서 읽기 또는 쓰기를 허용하여 외부로부터 데이터를 보호하고 데이터 무결성을 유지한다.
final
final을 붙이면 내용이나 값을 변경하지 못하게 된다.
final 변수 : 값을 더 이상 변경할수 없는 상수
final 메서드 : 내용을 더 이상 변경할수 없는 메서드, 오버라이딩 불가능
final 클래스 : 내용을 더 이상 변경할수 없는 클래스, 상속 불가능
다형성
여러 형태를 가지는 성질 이란 뜻으로, 여러 형태의 데이터타입 변수를 의미한다.
일반적인 객체생성과 참조변수 할당에는
A obj = new A(); 의 형태를 사용했지만,
다형성의 정의에 따라 부모 클래스 타입의 참조변수로 자식 클래스 타입의 객체를 참조할수도 있다.
A obj = new B(); // 클래스 B가 A를 상속할 때
클래스 B가 A를 상속하기 때문에 B 안에 A가 있다고 볼수 있기 때문이다.
이를 이용해 obj 하나로 A를 참조할수도, B를 참조할수도 있게 되는데 이를 다형성이라 한다.
다형성을 이용할 때 중요한 것은 부모 클래스 타입의 참조변수로 자손 객체를 참조하는 것은 가능하지만 반대의 경우에는 에러가 발생한다는 것이다.
Parents i = new Child(); 가능
Child i = new Parents; 불가능
Parents에 A, B, C 인스턴스가 있고, Child에 D 인스턴스가 있다면, 부모 클래스 타입을 참조변수로 사용하면 자식이 A, B, C를 상속받아 A, B, C, D를 사용할수 있지만, 반대의 경우에는 A, B, C를 상속받지 못한 상태에서 자식이 A, B, C를 사용하려고 할수 있기때문에 에러가 발생한다.
부모 클래스의 참조변수에서 자식 클래스의 인스턴스를 참조할 때 주의할 점은 부모가 자식의 인스턴스를 참조할때는 참조변수로 참조가 불가능한 멤버가 존재한다는 것이다.
부모 : A, B, C 사용가능, 자식의 D 사용불가 / 자식 : 부모의 A, B, C + 자신의 D 사용가능
다형성의 활용
package ch07;
class Animal {
void breath() {
System.out.println("숨쉬기");
}
}
class Lion extends Animal {
public String toString() {
return "사자";
}
}
class Rabbit extends Animal {
public String toString() {
return "토끼";
}
}
class Monkey extends Animal {
public String toString() {
return "원숭이";
}
}
class ZooKeeper {
void feed(Animal animal) {
System.out.println(animal + "에게 먹이 주기");
}
}
public class exam51 {
public static void main(String[] args) {
Lion lion1 = new Lion();
Rabbit rabbit1 = new Rabbit();
Monkey monkey1 = new Monkey();
ZooKeeper james = new ZooKeeper();
james.feed(lion1);
james.feed(rabbit1);
james.feed(monkey1);
}
}
다형성을 활용해서 각각 lion, rabbit, monkey의 데이터 타입을 Animal로 받아서 하나의 출력문으로 사자, 토끼, 원숭이 에게 먹이주기를 모두 출력할수 있다.
이는 사자, 토끼, 원숭이가 모두 Animal의 자식 클래스이기 때문이다.
코드의 흐름을 살펴보면 메인메서드에서 먼저 사자, 토끼, 호랑이의 객체의 주소를 각각 lion1, rabbit1, monkey1에 저장한다.
그 후, james 라는 객체의 feed 메서드를 저장한 주소를 이용해서 실행한다.
ZooKeeper 클래스에서 입력한 주소를 이용해 해당하는 클래스에서 animal 값을 구해서 출력문에 입력한다.
출력문에 의해 animal + "에게 먹이주기" 가 출력된다.
인터페이스
다중상속의 개념으로, 자바에서 상속은 하나의 부모에게서만 상속받을수 있지만, 인터페이스는 제약을 두는 대신 여러 부모에게서 상속을 받을수 있게 한다.
interface 인터페이스이름 { // 클래스와 다르게 class대신 interface를 쓰지만 클래스이다.
public static final 타입 이름 = 값;
public abstract 반환타입 메서드이름(매개변수);
}
인터페이스는 상수와 추상 메서드를 멤버로 가질수 있으며, 따로 붙이지 않아도 변수 앞에는 public static final이 메서드 앞에는 public abstract가 자동으로 붙게된다.
이를 이용해 인터페이스로 다중으로 상속받을때 같은 이름의 변수를 배제하고, 함수를 반드시 오버라이딩 하도록 하여 form의 목적으로 주로 쓰인다.
인터페이스의 상속은 implements 를 이용해서 한다.
interface A {
// 부모 인터페이스 A
}
class B implements A {
// 인터페이스를 상속받은 클래스 B
}
인터페이스는 주로 다형성과 함께 쓰이며, 인터페이스로 폼을 만들어두고 폼을 바탕으로 여러가지 클래스를 미리 만들어두고 필요에 따라 갈아 끼우는 형식으로 클래스를 변경할수 있다.
'프로그래밍 공부' 카테고리의 다른 글
2025.01.21 java 공부 (0) | 2025.01.21 |
---|---|
2025.01.20 java 정리 (0) | 2025.01.20 |
2025.01.16 java 공부 (0) | 2025.01.16 |
2025.01.15 java 공부 (0) | 2025.01.15 |
2025.01.14 java 공부 (0) | 2025.01.14 |