상속( inheritance )
- 기존의 클래스를 재사용하여 새로운 클래스를 작성한 것.
- 구현 방법
- 클래스의 이름 뒤에 상속받고자 하는 클래스의 이름을 키워드 'extends'와 함 께 작성. ( ex. class Child extends Parents )
class Child extends Parent {
}
class Parent{}
- 특징
- 생성자와 초기화 블록은 상속되지 않는다. 멤버만 상속된다.
- 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
- 조상 클래스는 자손 클래스의 공통적인 부분을 가지고 있어 각 클래스의 코드가 적어져서 관리가 용이함.
클래스간의 관계
- 포함관계 (composite)
- 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것을 뜻함.
- 선언방법
- Circle 클래스에 Point 클래스를 참조변수 c로 선언함.
class Circle{
Point c = new Point();
}
- 클래스간의 관계 결정하기
- 원(Circle)은 점(Point)이다. - 해당 말이 더 옳다고 보면 상속관계.
- 원(Circle)은 점(Point)을 가지고 있다. - 해당 말이 더 옳다고 보면 포함관계.
- 단일 상속(single inheritance)
- 자바에서는 다중상속의 문제점을 해결하기 위해 다중상속의 장점을 포기하고 단일 상속만을 허용한다.
- Object 클래스
- 모든 클래스 상속계층도의 최상위에 있는 조상클래스이다.
- 자바의 모든 클래스들은 Object클래스의 멤버들을 상속 받기 때문에 Object클래스에 정의된 멤버들을 사용할 수 있다.
오버라이딩(Overriding)
- 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩이라고 한다.
class Point {
int x;
int y;
String getLocation() {
return "x : " + x + ", y : " + y ;
}
}
class Point3D extends Point {
int z;
return "x : " + x + ", y : " + y + ", z : " + z;
}
- 조건(자손 클래스에서 오버라이딩 하는 메서드는 조상 클래스의 메서드와)
- 이름이 같아야 한다.
- 매개변수가 같아야 한다.
- 반환타입이 같아야 한다.
- 조상 클래스의 메서드를 자손 클래스에서 오버라이딩 할 때
- 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.
- 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
- 인스턴스메서드를 static 메서드로 또는 그 반대로 변경 할 수 없다.
- 오버로딩 vs 오버라이딩
- 오버로딩
- 기존에 없는 새로운 메서드를 정의하는 것 (new)
- 오버라이딩
- 상속받은 메서드의 내용을 변경하는 것(change, modify)
super
- 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.
- 조상 클래스의 멤버와 자손클래스의 멤버가 중복 정의되어 서로 구별 해야하는 경우에만 super를 사용.
- super()
- Super()는 조상 클래스의 생성자를 호출하는데 사용한다.
- 조상 클래스 멤버의 초기화 작업이 수행되어야 하기 때문에 자손 클래스의 생성자에서 조상 클래스의 생성자가 호출되어야 한다
- 선언
- Object클래스를 제외한 모든 클래스의 생성자 첫 줄에 this(), super()를 호출해야 한다.
- 호출 하지 않아도 컴파일러가 자동적으로 super()를 첫 줄에 삽입하여 문제가 없다.
- 조상 클래스의 멤버변수는 이처럼 조상의 생성자에 의해 초기화되도록 해야 한다.
Point3D(int x, int y, int z) {
super();
this.x = x;
this.y = y;
this.z = z;
}
Package 와 import
- 패키지(package)
- 클래스의 묶음.
- 패키지에는 클래스 또는 인터페이스를 포함시킬 수 있다.
- 클래스가 물리적으로 하나의 클래스파일인 것과 같이 패키지는 물리적으로 하나의 디렉토리이다.
- 선언
- 클래스나 인터페이스의 소스파일의 맨 위에 선언하면 된다.
- Import문
- Import문으로 사용하고자 하는 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명을 생략 할 수 있다.
- Ctrl + shift + o 로 자동으로 선언되게 할 수 있다.
- static import 문
- Static import문을 사용하면 static멤버를 호출할 때 클래스 이름을 생략가능.
제어자(modifier) - 캡슐화
- 클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다.
- 접근제어자
- Public, protected, default, private
- 그 외
- Static, final, abstract, native, transient, synchronized, volatile, strictfp
- static (클래스의, 공통적인)
- 클래스변수는 인스턴스에 관계없이 같은 값을 가진다.
- 하나의 변수를 모든 인스턴스가 공유를 한다.
- Static이 붙은 멤버변수와 메서드, 그리고 초기화 블록은 인스턴스 생성없이 사용가능하다.
- final(마지막의, 변경될 수 없는)
- 변수에 사용되면 값을 변경 할 수 없는 상수가 되며, 메서드에 사용되면 오버라이딩을 할 수 없게 되고 클래스에 사용되면 자신을 확장하는 자손클래스를 정의하지 못하게 된다.
- 생성자를 이용한 final멤버 변수의 초기화가 가능함.
- Abstract ( 추상의, 미완성의 )
- '미완성'의 의미를 가지고 있다. 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언하는데 사용한다.
- 접근 제어자 ( access modifier )
- 멤버 또는 클래스에 사용되어, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할을 함.
- Private : 같은 클래스 내에서만 접근이 가능
- Default : 같은 패키지 내에서만 사용이 가능
- Protected : 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.
- Public : 접근 제한이 전혀 없다.
- Public > protected > (default) > private
- 접근 제어자를 이용한 캡슐화
- 외부로부터 데이터를 보호하기 위해서
- 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서
- 제어자의 조합
- 메서드에 static과 abstract를 함께 사용이 불가함.
- 클래스에 abstract와 final을 동시에 사용할 수 없다.
- Abstract메서드의 접근 제어자가 private일 수 없다.
- 메서드에 private과 final을 같이 사용할 수 없다.
다형성( polymorphism )
- 여러 가지 형태를 가질 수 있는 능력
- 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조 할 수 있도록 한 것.
Tv t = new CaptionTv() ; // 조상 타입의 참조변수로 자손 인스턴스를 참조
- 특징
- 둘 다 같은 타입의 인스턴스지만 참조변수의 타입에 따라 사용 할 수 있는 멤버의 개수가 달라진다.
- 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.
- 반대로 자손타입이 참조변수로 조상타입의 인스턴스를 참조할 수 없다.
- 참조변수의 형변환
- 자손타입 -> 조상타입 (up-casting) : 형변환 생략가능
- 조상타입 -> 자손타입 (down-casting) : 형변환 생략불가
Car car = null;
FireEngine fe = new FireEngine();
FireEngine fe2 = null;
car = fe; // car = (Car)fe; 에서 형변환이 생략됨. 업캐스팅
fe2 = (FireEngine)car; // 형변환 생략불가. 다운캐스팅
- Car차입의 참조변수 c를 object로 형변환시 생략이 가능한 것은 object가 상위타입이기 때문이다.
- 형변환은 참조변수의 타입을 변환한 것이지 인스턴스를 변환하는 것은 아니기 때문에 인스턴스에는 아무런 영향이 없다.
- 조상의 인스턴스 객체를 가진 자손의 참조변수를 직접적으로 자손타입 참조변수에 넘기는 것은 불가능하다.
- 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요하다.
- Instanceof연산자
- 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 사용됨.
- Instanceof를 이용한 연산결과로 true를 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 의미함.
- 참조변수와 인스턴스의 연결
- 멤버변수가 조상 클래스와 자손 클래스에 중복으로 정의된 경우, 조상타입의 참조변수를 사용했을 때는 조상 클래스에 선언된 멤버변수가 사용되고, 자손타입의 참조변수를 사용했을 때는 자손 클래스에 선언된 멤버변수가 사용된다.
- 참조변수의 타입에 따라 결과가 달라지는 경우는 조상 클래스의 멤버변수와 같은 이름의 멤버변수를 자손 클래스에 중복해서 정의한 경우이다.
- 매개변수의 다형성
- 매개변수가 Product타입의 참조변수라는 것은 메서드의 매개변수로 Product클래스의 자손타입의 참조변수면 어느 것이나 매개변수로 받을 수 있다는 뜻이다.
- 여러 종류의 객체를 배열로 다루기
- 조상타입의 참조변수 배열을 사용하면, 공통의 조상을 가진 서로 다른 종류의 객체를 배열로 묶어서 다룰 수 있다.
class Buyer {
int money = 1000;
int bonusPoint = 0;
Product[] item = new Product[10];
int i = 0;
void buy(Product p) {
if(money , p.price) {
System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
return;
}
money -= p.price;
bonusPoint += p.bonusPoint;
intem[i++] = p;
System.out.println(p + "을/를 구입하였습니다.");
}
}
- Vector 메소드
- 10개의 객체를 저장할 수 있는 vector인스턴스를 생성한다.
- 10개 이상의 인스턴스가 저장되면, 자동적으로 크기가 증가된다.
- 선언
Vector item = new Vector() ;
추상클래스 ( abstract class )
- 추상클래스로 인스턴스를 생성할 수 없다.
- 추상클래스는 상속을 받은 자손클래스에 의해서만 완성이 될 수 있다.
- 추상클래스에도 생성자가 있으며, 멤버변수와 메서드도 가질 수 있다.
- 추상메서드
- 선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 둔 것이 추상메서드이다.
- 상속받는 자손 클래스는 조상의 추상메서드를 상황에 맞게 적절히 구현해줘야 한다.
- 'abstract'를 앞에 붙여주고, 구현부가 없으니 {}가 없다.
- 추상클래스의 작성
- 추상화는 기존의 클래스의 공통부분을 뽑아내서 조상 클래스를 만드는 것.
- 추상메서드를 선언하는 이유는 자손 클래스에서 추상메서드를 반드시 구현하도록 강요한 것.
- 조상클래스가 추상메서드라도 자손이 상속을 받아 구현한 메서드를 사용이 가능함.
인터페이스(interface)
- 추상클래스보다 추상화 정도가 높아서 추상클래스와 달리 몸통을 갖춘 일반 메서드 또는 멤버변수 구성원을 가질 수 없다. (추상클래스와 인터페이스의 차이점)
- 추상메서드와 상수만 받을 수 있다.
- 인터페이스의 작성
interface 인터페이스이름{
Public static final 타입 상수이름 = 값;
Public abstract 메서드이름 (매개변수목록);
- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.
- 모든 메서드는 public abstract이어야 하며, 이를 생략할 수 있다.
- Static 과 default는 제외.
- 인터페이스 상속
- 인터페이스는 인터페이스로부터만 상속을 받을 수 있다.
- 클래스와 달리 다중상속이 가능하다.
- 인터페이스 구현
- Extends 대신 implements를 사용한다.
- 구현하는 인터페이스 메서드 중 일부만 구현한다면 abstract를 붙여서 추상클래스로 구현 해야 한다.
- 자손타입은 조상상속과 인터페이스 구현을 동시에 할 수 있다.
- 인터페이스를 구현하는 클래스는 반드시 public으로 구현해야 한다. (인터페이스가 public abstract 이기 때문)
- 인터페이스를 이용한 다중상속
- 인터페이스는 static상수만 정의할 수 있으므로 조상클래스의 멤버변수와 충돌하는 경우는 거의 없다. (클래스에 이름을 붙여서 구별도 가능함.)
- 메서드이름이 일치하여도 인터페이스는 추상이기 때문에 조상쪽 메서드를 상속 받으면 됨.
- 다중상속 필요시 불러올 클래스 참조변수에 해당 인스턴스를 참조하여 사용할 것 ( 관계 - 포함 내용임.)
- 인터페이스를 이용한 다형성
- 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조 할 수 있으며, 인터페이스 타입으로 형변환도 가능하다.
- 리턴타입
- 리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미함.
Fightable method() {
Fightable f = new Fightable();
return f;
}
- 인터페이스의 장점
- 개발시간을 단축
- 표준화가 가능
- 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
- 독립적인 프로그래밍이 가능하다.
- 인터페이스의 이해
- 클래스를 사용하는 쪽과 클래스를 제공하는 쪽이 있다.
- 메서드를 사용하는 쪽에서는 사용하려는 메서드의 선언부만 알면 된다.
- 클래스 A는 여전히 클래스 B의 메서드를 호출하지만, 클래스 A는 인터페이스 I하고만 직접적인 관계에 있기 때문에 클래스 B의 변경에 영향을 받지 않는다.
- 인스턴스 참조변수로도 Object를 메서드를 호출 가능함.
- 디폴트 메서드와 static 메서드
- 추상 메서드의 기본적인 구현을 제공하는 메서드
- 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다.
- 여러 인터페이스의 디폴트 메서드 간의 충돌
- 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩 해야 한다.
- 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
- 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.
- 내부 클래스
- 클래스 안의 클래스
class A {
...
class B {}
}
- 장점
- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근 할 수 있다.
- 코드의 복잡성을 줄일 수 있다.(캡슐화)
class AAA {
int i = 100;
BBB b = new BBB();
class BBB {
void method() {
System.ote.println(i);
}
}
}
- 종류와 특징
내부 클래스 | 특징 |
인스턴스 클래스 (instance class) |
외부 클래스의 멤버변수 선언위치에 선언. 외부 클래스의 인스턴스멤버 처럼 다루어진다. 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용될 목적으로 선언된다. |
스태틱 클래스 (static class) |
외부 클래스의 멤버변수 선언위치에 선언하며, 외부 클래스의 static멤버처럼 다루어진다. 주로 외부 클래스의 static멤버, 특히 static 메서드에서 사용될 목적으로 선언된다. |
지역 클래스 (local class) |
외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 영역 내부에서만 사용될 수 있다. |
익명 클래스 (anonymous class) |
클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스 (일회용) |
- 접근제어자와 접근성
- 내부 클래스의 제어자는 변수에 사용 가능한 제어자와 동일
- Static 클래스만 static멤버를 정의 할 수 있다.
- 예외로 instance 와 local 내부 클래스에도 final상수에 static 붙일 수 있다.
class EX7_13 {
class InstanceInner {}
static class StaticInner {}
InstanceInner iv = new InstanceInner();
static StaticInner cv = new StaticInner();
static void staticMethod() {
StaticInner obj2 = new StaticInner();
Ex7_13 outer = new EX7_13();
InstanceInner obj1 = outer.new InstanceInner();
}
void instanceMethod() {
InstanceInner obj1 = new InstanceInner();
StaticInner obj2 = new StaticInner();
}
void method() {
class LocalInner{}
LocalInner lv = new LocalInner();
}
}
- 내부클래스에서 외부 클래스의 private멤버도 접근가능하다.
- 내부클래스에서 접근 가능한 지역변수는 외부 클래스에 final이 붙은 상수만 접근가능하다.
- 내부클래스 인스턴스를 생성하려면 외부클래스의 인스턴스를 생성 후에 사용해야함.
- static 내부클래스는 바로 인스턴스 생성이 가능함.
'Language > Java' 카테고리의 다른 글
정규식(Regular Expression) (0) | 2023.03.25 |
---|---|
(Java)10진법 <--> n집법 변환 (0) | 2023.03.16 |
Chapter5. 배열(Array) (0) | 2022.12.03 |
Chapter4. 조건문과 반복문 (0) | 2022.12.03 |
Chapter3. 연산자(Operator) (0) | 2022.12.03 |