extends
키워드 사용)// Tv - 조상 클래스
class Tv {
boolean power;
int channel;
}
// SmartTv - 자손 클래스
class SmartTv **extends Tv** {
String text;
}
class Point {
int x;
int y;
}
clas Circle {
Point c = new Point();
int r;
}
스포츠카
는 차
다.class SportsCar extends Car {
//...
}
원
은 점
을 가지고 있다.class Point {
int x;
int y;
}
clas Circle {
Point c = new Point();
int r;
}
Diamond Problem
extends Object
를 자동으로 추가해준다.Object 클래스
이다.toString()
, equals(Object o)
class Point {
int x;
int y;
String getLocation() {
return "x :" + x + ", y:" + y;
}
}
class Point3D extends Point {
int z;
String getLocation() {
return "x :" + x + ", y :" + y + ", z :" + z;
}
}
class Parent {
void parentMethod() {}
}
class Child extends Parent {
void parentMethod() {} // 오버라이딩
void parentMethod(int i) {} // 오버로딩
void childMethod() {}
void childMethod(int i) {} // 오버로딩
void childMethod() {} // Error! 중복 정의
}
super
를 붙여 구별this
와 super
가 지역변수로 존재 →자신이 속한 인스턴스의 주소가 자동 저장super();
자동 삽입class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
class Point3D extends Point {
int z;
Point3D(int x, int y, int z) {
super(x, y); // Point(int x, int y) 생성자 호출
this.z = z;
}
}
java.lang.String
);
사용String
, Object
, System
등import
: 클래스의 패키지명 생략 가능static import
: static 멤버 호출 시, 클래스 이름 생략 가능import static java.lang.Integer.*; // Integer 클래스의 모든 static 메서드
import static java.lang.Math.random; // Math.random()만. 괄호 안붙인다
import static java.lang.System.out; // System.out을 out만으로 참조 가능
Class Ex7_6 {
public static void main(String[]args){
// System.out.prntln(Math.random());
out.println(random());
// System.out.println("Math.PI :" + Math.PI);
out.println("Math.PI :" + PI)
}
}
static
이 사용될 수 있는 곳 - 멤버변수, 메서드, 초기화 블럭final
이 사용될 수 있는 곳 - 클래스, 메서드, 멤버변수, 지역변수fianl
클래스 : 상속 불가. 조상이 될 수 없다. 자손을 만들 수 없다.String
, Math
fianl
메서드 : 오버라이딩 불가fianl
멤버/지역 변수 : 상수class FinalTest {
final int x;
final int y;
final int z;
public FinalTest(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
}
abstract
가 사용될 수 있는 곳 - 클래스, 메서드abstract(추상)
메서드 : 선언부만 작성되어 있고 실제 수행내용은 없다.abstract(추상)
클래스 : 추상 메서드를 가진 클래스접근 제어자
가 사용될 수 있는 곳 - 클래스, 멤버변수, 메서드, 생성자private
: 같은 클래스 내에서만 접근 가능(default)
: 같은 패키지 내에서만 접근 가능protected
: 같은 패키지 + 다른 패키지 자손 클래스 접근 가능public
: 접근 제한 없음
- 클래스 : public, (default), final, abstract
- 메서드 : 모든 접근제어자, final, abstract, static
- 멤버변수 : 모든 접근제어자, final, static
- 지역변수 : final
public
, (default)
만 가능하다!static
, abstract
동시 사용 불가static
메서드는 몸통이 있는 메서드에만 사용할 수 있다.abstract
, final
동시 사용 불가fianl
- 클래스를 확장할 수 없다. 상속할 수 없다.abstract
- 상속을 통해 완성되어야 한다.abstract
메서드의 접근 제어자 private
불가abstract
메서드는 자손 클래스에서 구현하기 위해 접근 가능해야 한다.private
, final
동시 사용할 필요 없음private
or protected
로 제한하고, getter
/ setter
를 public
메서드로 제공class Tv {
boolean power;
int channel;
}
class SmartTv extends Tv {
String text;
}
class Exercise {
public static void main(String[] args) {
SmartTv s = new SmartTv(); // 참조 변수와 인스턴스 타입 일치
Tv t = new SmartTv(); // 타입 불일치. 조상 타입의 참조변수로 자손 타입 인스턴스 참조
// s와 t의 인스턴스 타입은 SmartTv로 같지만,
// t는 Tv클래스의 멤버들(power, channel)만 사용할 수 있다.
SmartTv x = new Tv(); // Error! 허용 안 됨
}
}
class Car {
String color;
int door;
void drive() {
System.out.println("drive!");
}
void stop() {
System.out.println("stop!");
}
}
class FireEngine extends Car {
void water() {
System.out.println("water!");
}
}
class Example1 {
public static void main(String[] args) {
Car car = null;
FireEngine fe = new FireEngine();
FireEngine fe2 = null;
fe.water();
car = fe; // 조상타입 <- 자손타입. car = (Car)fe; 에서 형변환 생략
car.water(); // Error!
fe2 = (FireEngine)car; // 자손타입 <- 조상타입. 형변환(생략불가)
fe2.water();
}
}
car = ~~(Car)~~fe;
FireEngine
타입의 fe → 조상인 Car
타입으로 형변환FireEngine
이었다. → Car
가 조상타입이어서 형변환 가능car.water();
Car
타입의 참조변수이므로, Car
에 있는 멤버만 접근 가능하다.water()
메서드는 Car
클래스에 없으므로 사용할 수 없다.fe2 = (FireEngine)c;
Car
타입의 car → 자손인 FireEngine
타입으로 형변환FireEngine
이다. car = fe → Car car = new FireEngine();fe2.water();
FireEngine
타입의 참조변수이므로, FirEEngine
에 있는 멤버에 접근 가능하다.water()
메서드는 FireEngine
클래스에 있으므로 사용할 수 있다.class Example2 {
public static void main(String[] args) {
Car car = new Car();
Car car2 = null;
FireEngine fe = null;
car.drive();
fe = (FireEngine)car; // 런타임 에러!!
fe.drive();
}
}
fe = (FireEngine)car;
Car
타입의 car → 자손인 FireEngine
타입으로 형변환 시도Car
였다. 자손타입 x = new 조상타입();
(조상타입의 인스턴스를 자손타입의 참조변수로 참조)은 불가하다.(다형성) → 참조변수가 가리키는 인스턴스의 자손타입으로 형변환 허용 불가Car car = new Car();
→ Car car = new FireEngine();
으로 변경한다면 OK!참조변수
instanceof 타입(클래스명)
→ true : 형변환 가능void doWork(Car c) {
if (c instanceof FireEngine) { // 1. 형변환이 가능한지 확인
FireEngine fe = (FireEngine)c; // 2. 형변환
...
}
}
class Product {
int price;
int bonusPoint;
}
class Tv extends Product { }
class Computer extends Product { }
class Buyer {
int money = 1000;
int bonusPoint = 0;
void buy(Product p) { // Product 클래스의 자손타입 참조변수 모두 매개변수 가능
money -= p.price;
bonusPoint += p.bonusPoint;
}
}
class Example {
public static void main(String[] args) {
Buyer b = new Buyer();
Tv t = new Tv();
Computer c = new Computer();
b.buy(t);
b.buy(c);
}
}
Vector
클래스 : 동적으로 크기가 관리되는 객체 배열abstract(추상)
메서드 : 선언부만 작성되어 있고 실제 수행내용은 없다./* 주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명한다. */
abstract 리턴타입 메서드이름();
abstract(추상)
클래스 : 추상 메서드를 가진 클래스class Example {
public static void main(String[] args) {
Unit[] group = { new Marine(), new Tank(), new Dropship() };
for (int i = 0; i < group.length; i++)
group[i].move(100, 200);
}
}
abstract class Unit {
int x, y;
abstract void move(int x, int y);
}
class Marine extends Unit {
void move(int x, int y) { }
}
class Tank extends Unit {
void move(int x, int y) { }
}
class Dropship extends Unit {
void move(int x, int y) { }
}
Unit
클래스 타입의 객체 배열을 통해, 서로 다른 종류의 인스턴스를 묶을 수 있다.Unit
클래스 타입의 참조변수(group)로 move
메서드 호출 가능Object
클래스 타입의 배열로 묶을 수도 있지만, Object
클래스에는 move
메서드가 정의되어 있지 않다.public static final
이어야 하며, 생략 가능하다.public abstact
이어야 하며, 생략 가능하다.abstract
를 붙여 추상클래스로 선언해야 한다.interface 인터페이스이름 {
public static final 타입 상수이름 = 값; // 상수
public abstract 메서드이름(매개변수목록); // 추상메서드
}
class 클래스이름 implements 인터페이스이름 {
// 인터페이스에 정의된 추상메서드를 모두 구현해야 한다.
}
class Fighter implements Fightable {
public void move(int x, int y) { ... }
public void attack(Unit u) { ... }
}
abstract class Fighter implements Fightable {
public void move(int x, int y) { ...}
}
class Fighter extends Unit implements Fightable { ... }
abstract class Unit {
int x, y;
abstract void move(int x, int y);
}
interface Fightable {
// ...
}
// Fighter 클래스 -> 인터페이스 Fightable을 구현한 클래스
class Fighter extends Unit implements Fightable {
public void move(int x, int y) { /* ... */ }
public void attack(Fightable f) { /* ... */ } // 메서드 매개변수 타입으로 인터페이스 사용 가능
}
class Example1 {
public static void main(String[] args) {
Fighter fighter = new Fighter();
// attack 메서드 매개변수로 Fightable인터페이스를 구현한 Fighter클래스의 인스턴스 넘겨준다.
fighter.attack(new Fighter());
}
}
class Example2 {
public static void main(String[] args) {
// Fightable타입 참조변수 -(참조)-> Fighter 인스턴스
Fightable f = (Fightable)new Fighter();
Fightable f2 = new Fighter();
}
Fightable method() { // method 리턴타입이 Fightable 인터페이스
Fighter ff = new Fighter();
return ff; // return new Fighter(); 가능.
// Fightable인터페이스를 구현한 Fighter클래스의 인스턴스 주소 반환
}
}
두 객체 간 중간 다리 역할
선언(설계)과 구현 분리
디폴트 메서드
와 static 메서드
는 예외적으로 추가할 수 있다.static 메서드
: 인스턴스와 관계 없는 독립적인 메서드라 인터페이스에 추가해도 상관은 없다.디폴트 메서드
: 추상 메서드의 기본적인 구현을 제공하는 메서드이나, 추상 메서드가 아니기 때문에 인터페이스에 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다.default
키워드를 붙인다. (접근제어자는 생략 가능)
추상 메서드와 달리 { }
가 있어야 한다.
interface MyInterface {
void method();
void newMethod(); // 추상 메서드
default void newMethod2(){}; // default 메서드
}
여러 인터페이스의 디폴트 메서드 간 충돌
디폴트 메서드와 조상 클래스의 메서드 간 충돌
- 조상 클래스의 메서드 상속, 디폴트 메서드 무시
→ 그냥 필요한 쪽 메서드와 같은 내용으로 오버라이딩
new 조상클래스이름() {
// 멤버 선언
}
new 구현인터페이스이름() {
// 멤버 선언
}
class Ex7_19 {
public static void main(String[] args) {
Button b = new Button("Start");
b.addActionListener(**new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("ActionEvent occurred!!");
}
}** // 익명 클래스의 끝
);
} // main의 끝
}
[참고] <Java의 정석 - 기초편>