[Java] 객체지향 프로그래밍 2
7-01 상속
- 자손 클래스는 조상 클래스의 모든 멤버를 상속받는다. (단, 생성자와 초기화 블럭은 상속되지 않는다.)
- 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
class Parent { }
class Child extends Parent {
}
7-02 상속 예제
class Tv {
boolean power;
int channel;
void power() { power = !power; }
void channelUp() { ++channel; }
void channelDown() { --channel; }
}
class SmartTv extends Tv { // 스마트TV는 Tv에 캡션(자막)을 보여주는 기능을 추가
boolean caption; // 캡션상태 on/off
void displayCaption(String text) {
if (caption) {
System.out.println(text);
}
}
}
class Ex7_1 {
public static void main(String args[]) {
SmartTv stv = new SmartTv();
stv.channel = 10;
stv.channelUp();
System.out.println(stv.channel);
stv.displayCaption("Hello, World");
stv.caption = true;
stv.displayCaption("Hello, World");
}
}
7-03 클래스 간의 관계 - 포함관계
class Circle {
int x; // 원점의 x 좌표
int y; // 원점의 y 좌표
int r;
}
class Point {
int x;
int y;
}
class Circle {
Point c = new Point(); // 원점
int r;
}
7-04 클래스 간의 관계 결정하기
- 상속관계 : ‘~은 ~이다.(is-a)’
- 포함관계 : ‘~은 ~을 가지고 있다.(has-a)’
class Circle extends Point { // 상속관계 : 원은 점이다. int r; }
class Circle { Point c = new Point(); // 포함관계 : 원은 점을 가지고 있다. int r; }
7-05 단일 상속(single inheritance)
public TvDVD extends Tv, DVD { // 에러. 조상은 하나만 허용된다.
}
7-06 Object클래스 - 모든 클래스의 조상
- 모든 클래스 상속계층도의 최상위에 있는 조상클래스이다.
- 모든 클래스들은 자동적으로 Object클래스로부터 상속받는다.
- 주요 메서드로는 toString(), equals(Object o) 등이 있다.
7-07 오버라이딩(overriding)
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;
}
}
7-08 오버라이딩의 조건
- 조상 클래스의 메서드를 자손 클래스에서 오버라이딩할 때
- 선언부가 조상 클래스의 메서드와 일치해야 한다.
- 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
- 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
7-09 오버로딩 vs. 오버라이딩
- 오버로딩 : 기존에 없는 새로운 메서드를 정의하는 것(new)
- 오버라이딩 : 상속받은 메서드의 내용을 변경하는 것(change, modify)
class Parent {
void parentMethod() { }
}
class Child extends Parent {
void parentMethod() { } // 오버라이딩
void parentMethod(int i) { } // 오버로딩
void childMethod() { }
void childMethod(int i) { } // 오버로딩
void childMethod() { } // 에러. 중복정의 되었음.
}
7-10 참조변수 super
- super : 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.
class Ex7_2 {
public static void main(String args[]) {
Child c = new Child();
c.method();
}
}
class Parent { int x=10; } // super.x
class Child extends Parent {
int x=20; // this.x
void method() {
System.out.println("x=" + x);
System.out.println("this.x=" + this.x);
System.out.println("super.x="+ super.x);
}
}
결과 x = 20, this.x = 20, super.x = 10
7-11 super() - 조상의 생성자
class Point3D extends Point {
int z;
Point3D(int x, int y, int z) {
this.x = x; // 조상의 멤버를 초기화
this.y = y; // 조상의 멤버를 초기화
this.z = z;
}
}
Point3D(int x, int y, int z) {
super(x, y); // 조상클래스의 생성자 Point(int x, int y)를 호출
this.z = z;
}
7-12 패키지(package)
- 클래스의 묶음이다.
7-13 패키지의 선언
package 패키지명;
7-14 클래스 패스(classpath)
7-15 import문
import 패키지명.클래스명;
import 패키지명.*;
7-16 static import문
- static멤버를 호출할 때 클래스 이름을 생략할 수 있다.
import static java.lang.System.out;
import static java.lang.Math.*;
class Ex7_6 {
public static void main(String[] args) {
// System.out.println(Math.random());
out.println(random());
// System.out.println("Math.PI :"+Math.PI);
out.println("Math.PI :" + PI);
}
}
7-17 제어자(modifier)
- 접근 제어자 : public, protected, (default), private
- 그 외 : static, final, abstract, native, transient, synchronized, volatile, strictfp
7-18 static - 클래스의, 공통적인
- static이 사용될 수 있는 곳 - 멤버변수, 메서드, 초기화 블럭
class StaticTest {
static int width = 200; // 클래스 변수(static변수)
static int height = 120; // 클래스 변수(static변수)
static { // 클래스 초기화 블럭
// static변수의 복잡한 초기화 수행
}
static int max(int a, int b) { // 클래스 메서드(static메서드)
return a > b ? a : b;
}
}
7-19 final - 마지막의, 변경될 수 없는
- final이 사용될 수 있는 곳 - 클래스, 메서드, 멤버변수, 지역변수
final class FinalTest { // 조상이 될 수 없는 클래스
final int MAX_SIZE = 10; // 값을 변경할 수 없는 멤버변수(상수)
final void getMaxSize() { // 오버라이딩할 수 없는 메서드(변경불가)
final int LV = MAX_SIZE; // 값을 변경할 수 없는 지역변수(상수)
return MAX_SIZE;
}
}
7-20 abstract - 추상의, 미완성의
- abstract가 사용될 수 있는 곳 - 클래스, 메서드
abstract class AbstractTest { // 추상 클래스(추상 메서드를 포함한 클래스)
abstract void move(); // 추상 메서드(구현부가 없는 메서드)
}
7-21 접근 제어자(access modifier)
int add(int x, int y) {
int result = x + y;
return result;
}
int add(int x, int y) {
return x + y;
}
7-22 캡슐화와 접근 제어자
- 메서드가 호출되면 수행에 필요한 만큼의 메모리를 스택에 할당받는다.
- 메서드가 수행을 마치고 나면 사용했던 메모리를 반환하고 스택에서 제거된다.
- 호출스택의 제일 위에 있는 메서드가 현재 실행 중인 메서드이다.
- 아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드이다.
7-23 다형성(polymorphism)
- 기본형 매개변수 : 변수의 값을 읽기만 할 수 있다.
- 참조형 매개변수 : 변수의 값을 읽고 변경할 수 있다.
class Data { int x; }
class Ex6_6 {
public static void main(String[] args) {
Data d = new Data();
d.x = 10;
System.out.println("main() : x = " + d.x);
change(d.x);
System.out.println("After change(d.x)");
System.out.println("main() : x = " + d.x);
}
static void change(int x) { // 기본형 매개변수
x = 1000;
System.out.println("change() : x = " + x);
}
}
7-24 참조변수의 형변환
class Data2 { int x; }
class Ex6_7 {
public static void main(String[] args) {
Data2 d = new Data2();
d.x = 10;
System.out.println("main() : x = " + d.x);
change(d);
System.out.println("After change(d)");
System.out.println("main() : x = " + d.x);
}
static void change(Data2 d) { // 참조형 매개변수
d.x = 1000;
System.out.println("change() : x = " + d.x);
}
}
7-25 참조변수의 형변환 예제
class Data3 { int x; }
class Ex6_8 {
public static void main(String[] args) {
Data3 d = new Data3();
d.x = 10;
Data3 d2 = copy(d);
System.out.println("d.x ="+d.x);
System.out.println("d2.x="+d2.x);
}
static Data3 copy(Data3 d) {
Data3 tmp = new Data3(); // 새로운 객체 tmp를 생성한다.
tmp.x = d.x; // d.x의 값을 tmp.x에 복사한다.
return tmp; // 복사한 객체의 주소를 반환한다.
}
}
7-26 instanceof 연산자
메서드 중에서 인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드를 사용하지 않는) 메서드를 클래스 메서드(static 메서드)로 정의한다.
7-27 매개변수의 다형성
class MyMath2 {
long a, b;
// 인스턴스 변수 a, b만을 이용해서 작업하므로 매개변수가 필요없다.
long add() { return a + b; } // a, b는 인스턴스 변수
long subtract() { return a - b; }
long multiply() { return a * b; }
double divide() { return a / b; }
// 인스턴스 변수와 관계없이 매개변수만으로 작업이 가능하다.
static long add(long a, long b) { return a + b; } // a, b는 지역변수
static long subtract(long a, long b) { return a - b; }
static long multiply(long a, long b) { return a * b; }
static double divide(long a, long b) { return a / (double)b; }
}
class Ex6_9 {
public static void main(String args[]) {
// 클래스 메서드 호출. 인스턴스 생성없이 호출가능.
System.out.println(MyMath2.add(200L, 100L));
System.out.println(MyMath2.subtract(200L, 100L));
System.out.println(MyMath2.multiply(200L, 100L));
System.out.println(MyMath2.divide(200L, 100L));
MyMath2 mm = new MyMath2(); // 인스턴스를 생성.
mm.a = 200L;
mm.b = 100L;
// 인스턴스 메서드는 객체생성 후에만 호출이 가능함.
System.out.println(mm.add());
System.out.println(mm.subtract());
System.out.println(mm.multiply());
System.out.println(mm.divide());
}
}
7-28 매개변수의 다형성 예제
- 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙인다.
- 클래스 변수(static 변수)는 인스턴스를 생성하지 않아도 사용할 수 있다.
- 클래스 메서드(static 메서드)는 인스턴스 변수를 사용할 수 없다.
- 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
7-29 여러 종류의 객체를 배열로 다루기
- 같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다.
- 단, 클래스멤버가 인스턴스 멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다.
7-30 여러 종류의 객체를 배열로 다루기 예제
- 한 클래스 내에 같은 이름의 메서드를 여러 개 정의하는 것
- 메서드 이름이 같아야 한다.
- 매개변수의 개수 또는 타입이 달라야 한다.
- 반환 타입은 관계없다.
7-31 추상 클래스(abstract class)
class Ex6_10 {
public static void main(String args[]) {
MyMath3 mm = new MyMath3();
System.out.println("mm.add(3, 3) 결과:" + mm.add(3,3));
System.out.println("mm.add(3L, 3) 결과: " + mm.add(3L,3));
System.out.println("mm.add(3, 3L) 결과: " + mm.add(3,3L));
System.out.println("mm.add(3L, 3L) 결과: " + mm.add(3L,3L));
int[] a = {100, 200, 300};
System.out.println("mm.add(a) 결과: " + mm.add(a));
}
}
class MyMath3 {
int add(int a, int b) {
System.out.print("int add(int a, int b) - ");
return a+b;
}
long add(int a, long b) {
System.out.print("long add(int a, long b) - ");
return a+b;
}
long add(long a, int b) {
System.out.print("long add(long a, int b) - ");
return a+b;
}
long add(long a, long b) {
System.out.print("long add(long a, long b) - ");
return a+b;
}
int add(int[] a) { // 배열의 모든 요소의 합을 결과로 돌려준다.
System.out.print("int add(int[] a) - ");
int result = 0;
for(int i=0; i < a.length;i++)
result += a[i];
return result;
}
}
7-32 추상 메서드(abstract method)
- 인스턴스가 생성될 때 호출되는 ‘인스턴스 초기화 메서드’이다.
- 생성자의 이름은 클래스의 이름과 같아야 한다.
- 생성자는 리턴 값이 없다.
class Point {
Point() { // 매개변수가 없는 생성자.
}
Point(int x, int y) { // 매개변수가 있는 생성자.
}
}
7-33 추상클래스의 작성
- 기본 생성자가 컴파일러에 의해서 추가되는 경우는 클래스에 정의된 생성자가 하나도 없을 때 뿐이다.
7-34 추상클래스의 작성 예제
class Car {
String color;
String gearType;
int door;
Car() {} // 기본 생성자
Car(String c, String g, int d) { // 생성자
color = c;
gearType = g;
door = d;
}
}
// 생성자 Car() 사용한다면
Car c = new Car();
c.color = "white";
c.gearType = "auto";
c.door = 4;
// 생성자 Car(String color, String gearType, int door) 사용한다면
Car c = new Car("white", "auto", 4);
7-35 인터페이스(interface)
- 인스턴스를 생성할 때는 다음의 2가지 사항을 결정해야 한다.
- 클래스 - 어떤 클래스의 인스턴스를 생성할 것인가?
- 생성자 - 선택한 클래스의 어떤 생성자로 인스턴스를 생성할 것인가?
class Car {
String color;
String gearType;
int door;
Car() {}
Car(String c, String g, int d) {
color = c;
gearType = g;
door = d;
}
}
class Ex6_12 {
public static void main(String[] args) {
Car c1 = new Car();
c1.color = "white";
c1.gearType = "auto";
c1.door = 4;
Car c2 = new Car("white", "auto", 4);
System.out.println("c1의 color=" + c1.color + ", gearType=" + c1.gearType+ ", door="+c1.door);
System.out.println("c2의 color=" + c2.color + ", gearType=" + c2.gearType+ ", door="+c2.door);
}
}
7-36 인터페이스의 상속
- 생성자의 이름으로 클래스이름 대신 this를 사용한다.
- 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.
class Car2 {
String color;
String gearType;
int door;
Car2() {
this("white", "auto", 4);
}
Car2(String color) {
this(color, "auto", 4);
}
Car2(String color, String gearType, int door) {
this.color = color;
this.gearType = gearType;
this.door = door;
}
}
class Ex6_13 {
public static void main(String[] args) {
Car2 c1 = new Car2();
Car2 c2 = new Car2("blue");
System.out.println("c1의 color=" + c1.color + ", gearType=" + c1.gearType+ ", door="+c1.door);
System.out.println("c2의 color=" + c2.color + ", gearType=" + c2.gearType+ ", door="+c2.door);
}
}
7-37 인터페이스의 구현
- this : 인스턴스 자신을 가리키는 참조변수
- this(), this(매개변수) : 생성자, 같은 클래스의 다른 생성자를 호출할 때 사용한다.
- this는 ‘참조변수’이고, this()는 ‘생성자’이다.
7-38 인터페이스를 이용한 다형성
- 멤버변수(클래스 변수와 인스턴스 변수)와 배열의 초기화는 선택이지만, 지역변수의 초기화는 필수이다.
class Test {
int x; // 인스턴스 변수
int y = x; // 인스턴스 변수
void method1() {
int i; // 지역변수
int j = i; // 에러. 지역변수를 초기화하지 않고 사용
}
}
7-39 인터페이스의 장점
- 명시적 초기화
- 초기화
Leave a comment