2022-07-08
추상클래스
추상 클래스란 구체적이지 않은 클래스를 의미한다. 독수리, 타조는 구체적인 새를 지칭하는데 새, 포유류 같은 것은 구체적이지 않다.
이런 것을 구현한 클래스를 추상 클래스라고 한다.
추상 클래스 정의하기
- 추상 클래스는 클래스 앞에 abstract 키워드를 이용해서 정의한다.
- 추상 클래스는 미완성의 추상 메소드를 포함할 수 있다.
- 추상 메소드란, 내용이 없는 메소드 이다. 즉 구현이 되지 않은 메소드이다.
- 추상 메소드는 리턴 타입 앞에 abstract라는 키워드를 붙여야 한다.
- 추상 클래스는 인스턴스를 생성할 수 없다.
public abstract class Bird{
public abstract void sing();
public void fly(){
System.out.println("날다.");
}
}
추상 클래스를 상속받는 클래스 생성하기
- 추상 클래스를 상속받은 클래스는 추상 클래스가 갖고 있는 추상 메소드를 반드시 구현해야 한다.
- 추상 클래스를 상속받고, 추상 클래스가 갖고 있는 추상 메소드를 구현하지 않으면 해당 클래스도 추상 클래스가 된다.
public class Duck extends Bird{
@Override
public void sing() {
System.out.println("꽥꽥!!");
}
}
사용하기
- Bird는 추상 클래스 이므로 객체를 생성할 수 없다.
public class DuckExam {
public static void main(String[] args) {
Duck duck = new Duck();
duck.sing();
duck.fly();
//Bird b = new Bird();
}
}
super와 부모생성자
class가 인스턴스화 될때 생성자가 실행되면서 객체의 초기화를 한다. 그 때 자신의 생성자만 실행이 되는것이 아니고, 부모의 생성자부터 실행된다.
부모 생성자
public class Car{
public Car(){
System.out.println("Car의 기본생성자입니다.");
}
}
public class Bus extends Car{
public Bus(){
System.out.println("Bus의 기본생성자입니다.");
}
}
- 생성자 테스트
public class BusExam{
public static void main(String args[]){
Bus b = new Bus();
}
}
- 결과
Car의 기본생성자입니다. Bus의 기본생성자입니다.
- new 연산자로 Bus객체를 생성하면, Bus객체가 메모리에 올라갈때 부모인 Car도 함께 메모리에 올라간다.
- 생성자는 객체를 초기화 하는 일을한다.
- 생성자가 호출될 때 자동으로 부모의 생성자가 호출되면서 부모객체를 초기화 하게된다.
super
- 자신을 가리키는 키워드가 this 라면, 부모들 가리키는 키워드는 super
- super() 는 부모의 생성자를 의미한다.
- 부모의 생성자를 임의로 호출하지 않으면, 부모 class의 기본 생성자가 자동으로 호출된다.
- 아래 예제처럼 호출해보면 위에서 super()를 호출하지 않을때와 결과가 같다.
public Bus(){
super();
System.out.println("Bus의 기본생성자입니다.");
}
부모의 기본생성자가 아닌 다른 생성자를 호출하는 방법
- 클래스는 기본 생성자가 없는 경우도 존재한다.
public class Car{
public Car(String name){
System.out.println(name + " 을 받아들이는 생성자입니다.");
}
}
- Car class가 위 처럼 수정되면, Bus생성자에서 컴파일 오류가 발생한다.
- 부모가 기본생성자가 없기 때문에 컴파일 오류가 발생하게 되는 것이다.
- 이런 문제를 해결하려면 자식 클래스의 생성자에서 직접 부모의 생성자를 호출해야 합니다.
public Bus(){
super("소방차"); // 문자열을 매개변수로 받는 부모 생성자를 호출하였다.
System.out.println("Bus의 기본생성자입니다.");
}
super 키워드는 자식에서 부모의 메소드나 필드를 사용할 때도 사용합니다.
클래스 형변환
부모타입으로 자식객체를 참조하게 되면 부모가 가지고 있는 메소드만 사용할 수 있다. 자식객체가 가지고 있는 메소드나 속성을 사용하고 싶다면 형변환 해야 한다.
형변환
public class Car{
public void run(){
System.out.println("Car의 run메소드");
}
}
public class Bus extends Car{
public void ppangppang(){
System.out.println("빵빵.");
}
}
상속관계란 is a 관계라고 말했었습니다. "Bus는 Car다." 라는 관계가 성립되는 것이죠.
현실에서도 우리는 버스를 가리키면서 차다. 라고 말하곤 합니다.
- 부모타입으로 자식객체를 참조할 수 있다.
- 부모타입으로 자식객체를 참조하게 되면 부모가 가지고 있는 메소드만 사용할 수 있다.
public class BusExam{
public static void main(String args[]){
Car car = new Bus();
car.run();
car.ppangppang(); // 컴파일 오류 발생
}
}
- ppangppang()메소드를 호출하고 싶다면 Bus타입의 참조변수로 참조해야 한다.
public class BusExam{
public static void main(String args[]){
Car car = new Bus();
car.run();
//car.ppangppang(); // 컴파일 오류 발생
Bus bus = (Bus)car; //부모타입을 자식타입으로 형변환
bus.run();
bus.ppangppang();
}
}
- 객체들 끼리도 형변환이 가능하다. 단 상속관계에 있었을 때만 가능하다.
- 부모타입으로 자식타입의 객체를 참조할 때는 묵시적으로 형변환이 일어난다.
- 부모타입의 객체를 자식타입으로 참조하게 할때는 명시적으로 형변환 해주어 한다. 단 이렇게 형변환 할때에는 부모가 참조하는 인스턴스가 형변환 하려는 자식타입일 때만 가능하다.
▶ 인터페이스 만들기
인터페이스: 서로 관계가 없는 물체들이 상호 작용을 하기 위해서 사용하는 장치나 시스템
- 인터페이스 정의하는 방법
- 추상 메소드와 상수를 정의 할 수 있다.
public interface TV{
public int MAX_VOLUME = 100;
public int MIN_VOLUME = 0;
public void turnOn();
public void turnOff();
public void changeVolume(int volume);
public void changeChannel(int channel);
}
인터페이스에서 변수를 선언하면 컴파일시 자동으로 아래와 같이 바뀐다.
public static final int MAX_VOLUME = 100;
public static final int MIN_VOLUME = 0;
인터페이스에서 정의된 메소드는 모두 추상 메소드이다. 위에서 선언된 모든 메소드는 컴파일 시에 다음과 같이 자동으로 변경된다.
public abstract void on();
public abstract void off();
public abstract void volume(int value);
public abstract void channel(int number);
▶ 인터페이스 사용하기
- 인터페이스 사용하는 방법
- 인터페이스는 사용할때 해당 인터페이스를 구현하는 클래스에서 implements 키워드를 이용한다.
public class LedTV implements TV{
public void on(){
System.out.println("켜다");
}
public void off(){
System.out.println("끄다");
}
public void volume(int value){
System.out.println(value + "로 볼륨조정하다.");
}
public void channel(int number){
System.out.println(number + "로 채널조정하다.");
}
}
- 인터페이스가 가지고 있는 메소드를 하나라도 구현하지 않는다면 해당 클래스는 추상클래스가 된다.(추상클래스는 인스턴스를 만들 수 없음)
public class LedTVExam{
public static void main(String args[]){
TV tv = new LedTV();
tv.on();
tv.volume(50);
tv.channel(6);
tv.off();
}
}
- 참조변수의 타입으로 인터페이스를 사용할 수 있다. 이 경우 인터페이스가 가지고 있는 메소드만 사용할 수 있다.
- 만약 TV인터페이스를 구현하는 LcdTV를 만들었다면 위의 코드에서 new LedTV부분만 new LcdTV로 변경해도 똑같이 프로그램이 동작할 것다. 동일한 인터페이스를 구현한다는 것은 클래스 사용법이 같다는 것을 의미한다.
- 클래스는 이러한 인터페이스를 여러개 구현할 수 있다.
인터페이스의 default method
인터페이스의 default 메소드
JAVA 8이 등장하면서 interface에 대한 정의가 몇 가지 변경되었다.
default메소드
- 인터페이스가 default키워드로 선언되면 메소드가 구현될 수 있다. 또한 이를 구현하는 클래스는 default메소드를 오버라이딩 할 수 있다.
public interface Calculator {
public int plus(int i, int j);
public int multiple(int i, int j);
default int exec(int i, int j){ //default로 선언함으로 메소드를 구현할 수 있다.
return i + j;
}
}
//Calculator인터페이스를 구현한 MyCalculator클래스
public class MyCalculator implements Calculator {
@Override
public int plus(int i, int j) {
return i + j;
}
@Override
public int multiple(int i, int j) {
return i * j;
}
}
public class MyCalculatorExam {
public static void main(String[] args){
Calculator cal = new MyCalculator();
int value = cal.exec(5, 10);
System.out.println(value);
}
}
- 인터페이스가 변경이 되면, 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제가 있다. 이런 문제를 해결하기 위하여 인터페이스에 메소드를 구현해 놓을 수 있도록 하였다.
static메소드
public interface Calculator {
public int plus(int i, int j);
public int multiple(int i, int j);
default int exec(int i, int j){
return i + j;
}
public static int exec2(int i, int j){ //static 메소드
return i * j;
}
}
//인터페이스에서 정의한 static메소드는 반드시 인터페이스명.메소드 형식으로 호출해야한다.
public class MyCalculatorExam {
public static void main(String[] args){
Calculator cal = new MyCalculator();
int value = cal.exec(5, 10);
System.out.println(value);
int value2 = Calculator.exec2(5, 10); //static메소드 호출
System.out.println(value2);
}
}
- 인터페이스에 static 메소드를 선언함으로써, 인터페이스를 이용하여 간단한 기능을 가지는 유틸리티성 인터페이스를 만들 수 있게 되었다.
내부클래스
내부 클래스란 클래스 안에 선언된 클래스
어느 위치에 선언하느냐에 따라서 4가지 형태가 있을 수 있다.- 첫번째는 클래스 안에 인스턴스 변수, 즉 필드를 선언하는 위치에 선언되는 경우. 보통 중첩클래스 혹은 인스턴스 클래스라고 한다.
- 내부에 있는 Cal객체를 생성하기 위해서는, 밖에는 InnerExam1의 객체를 만든 후에 InnerExam1.Cal cal = t.new Cal();과 같은 방법으로 Cal객체를 생성한 후 사용한다.
public class InnerExam1{
class Cal{
int value = 0;
public void plus(){
value++;
}
}
public static void main(String args[]){
InnerExam1 t = new InnerExam1();
InnerExam1.Cal cal = t.new Cal();
cal.plus();
System.out.println(cal.value);
}
}
- 두번째는 내부 클래스가 static으로 정의된 경우, 정적 중첩 클래스 또는 static 클래스라고 한다.
- 필드 선언할 때 스태틱한 필드로 선언한 것과 같다. 이 경우에는 InnerExam2객체를 생성할 필요없이 new InnerExam2.Cal() 로 객체를 생성할 수 있다.
public class InnerExam2{
static class Cal{
int value = 0;
public void plus(){
value++;
}
}
public static void main(String args[]){
InnerExam2.Cal cal = new InnerExam2.Cal();
cal.plus();
System.out.println(cal.value);
}
}
- 세번째로는 메소드 안에 클래스를 선언한 경우, 지역 중첩 클래스 또는 지역 클래스라고 한다.
- 메소드 안에서 해당 클래스를 이용할 수 있다.
public class InnerExam3{
public void exec(){
class Cal{
int value = 0;
public void plus(){
value++;
}
}
Cal cal = new Cal();
cal.plus();
System.out.println(cal.value);
}
public static void main(String args[]){
InnerExam3 t = new InnerExam3();
t.exec();
}
}
- 네번재로는 익명클래스가 있다.
익명클래스
익명 중첩 클래스는 익명 클래스라고 보통 말하며, 내부 클래스이기도 하다.
//추상클래스 Action
public abstract class Action{
public abstract void exec();
}
//추상클래스 Action을 상속받은 클래스 MyAction
public class MyAction extends Action{
public void exec(){
System.out.println("exec");
}
}
//MyAction을 사용하는 클래스 ActionExam
public class ActionExam{
public static void main(String args[]){
Action action = new MyAction();
action.exec();
}
}
//MyAction을 사용하지 않고 Action을 상속받는 익명 클래스를 만들어서 사용하도록 수정해 보도록 하겠습니다.
public class ActionExam{
public static void main(String args[]){
Action action = new Action(){
public void exec(){
System.out.println("exec");
}
};
action.exec();
}
}
- 생성자 다음에 중괄호 열고 닫고가 나오면, 해당 생성자 이름에 해당하는 클래스를 상속받는 이름없는 객체를 만든다는 것을 뜻한다.
- 괄호 안에는 메소드를 구현하거나 메소드를 추가할 수 있다. 이렇게 생성된 이름 없는 객체를 action이라는 참조변수가 참조하도록 하고, exec()메소드를 호출.
- 익명클래스를 만드는 이유는 Action을 상속받는 클래스를 만들 필요가 없을 경우이다.
- Action을 상속받는 클래스가 해당 클래스에서만 사용되고 다른 클래스에서는 사용되지 않는 경우이다.
'IT > JAVA' 카테고리의 다른 글
[17일차] JAVA Generic / lambda (0) | 2022.07.12 |
---|---|
[16일차] JAVA 예외처리. 스레드 (0) | 2022.07.11 |
[15일차] JAVA (0) | 2022.07.08 |
[14일차] JAVA 객체지향 (0) | 2022.07.07 |
JAVA Programmers 개념 정리 (0) | 2022.07.06 |
댓글