1. 상속
1.1 상속(ingeritance)의 정의와 장점
▶ 상속이란?
- 기존의 클래스를 재사용해서 새로운 클래스를 작성하는 것.
- 두 클래스를 부모와 자식으로 관계를 맺어주는 것.
- 자식은 부모의 모든 멤버를 상속받는다.(생성자, 초기화블럭 제외)
- 자식의 멤버개수는 부모보다 적을 수 없다.(같거나 많다)
class 자식클래스 extends 부모클래스{
//...
}
ex)
class Point{
int x;
int y;
}
class Point3D{
int x;
int y;
int z;
}
▼
class Point3D extends Point{
int z;
}
1.2 클래스 간의 관계 - 상속 관계(ingeritance)
- 공통부분은 부모에서 관리하고 개별부분은 자식에서 관리한다.
- 부모의 변경은 자식에 영향을 미치지만, 자식의 변경은 부모에 아무런 영향을 미치지않는다.
class Parent {}
class Child extends Parent {}
class Child2 extends Parent {}
class GrandChild extends Child {}
1.2 클래스 간의 관계 - 포함관계(composite)
▶ 포함(composite)이란?
- 한 클래스의 멤버변수로 다른 클래스를 선언하는 것
- 작은 단위의 클래스를 먼저 만들고, 이 들을 조합해서 하나의 커다란 클래스를 만든다.
class Circle {
int x; //원점의 x좌표
int y; //원점의 y좌표
int r; //반지름(radius)
}
▼
class Circle {
Point c = new Point(); //원점
int r; //반지름(radius)
}
class Car{
Engine e = new Engine(); //엔진
Door[] d= new Door[4]; //문, 문의 개수를 넷으로 가정하고 배열로 처리햇다.
}
1.3 클래스 간의 관계 결정하기 - 상속 vs 포함
- 가능한 한 많은 관계를 맺어주어 재사용성을 높이고 관리하기 쉽게 한다.
- 'is-a'와 'has-a'를 가지고 문장을 만들어 본다.
원(Circle)은 점(Point)이다. - Circle is a Point.
원(Circle)은 점(Point)을 가지고 있다. - Circle has a Point.
상속 관계 - '~은 ~이다. (is-a)'
포함 관계 - '~은 ~을 가지고 있다.(has-a)'
class Circle extends Point{
int r; //반지름(radius)
}
▼
class Circle{
Point c = new Point(); //원점
int r; //반지름(radius)
}
1.3 클래스 간의 관계 결정하기 - 예제 설명
- 원(Circle)은 도형(Shape)이다.(A Circle is a Shape.) : 상속관계
- 원(Circle)은 점(Point)를 가지고 있다.(A Circle has a Point.) : 포함관계
class Shape{
String color = "blue";
void draw(){
//도형을 그린다.
}
}
class Point{
int x;
int y;
Point(){
this(0,0);
}
Point(int x, int y){
this.x=x;
this.y=y;
}
}
class Circle extends Shape{
Point cneter;
int x;
Circle(){
this(new Point(0,0),100);
}
Circle(Point center, int r){
this.center = center;
this.r = r;
}
}
class Triangle extends Shape{
Point[] p;
Triangle(Point[] p){
this.p = p;
}
Triangle(Point p1, Point p2, Point p3){
p = new Point[]{p1,p2,p3};
}
}
Circle c1 = new Circle();
Circle c2 = new Circle(new Point(150,150),50);
Point[] p = {new Point(100,100),
new Point(140,50),
new Point(200,100)
};
Triangle t1 = new Triangle(p);
1.3 클래스 간의 관계 결정하기 - 예제 설명2
class Deck{
final int CARD_NUM = 52; //카드의 개수
Card c[] = new Card[CARD_NUM];
Deck(){ //Deck의 카드를 초기화한다.
int i=0;
for(int k=Card.KIND_MAX; k>-; k--){
for(int n=1; n<Card.NUM_MAX+1; n++){
c[i++] = new Card(k, n);
}
}
}
}
Card pick(int index){ //지정된 위치(index)에 있는 카드 하나를 선택한다.
return c[index%CARD_NUM];
}
Card pick(){ //Deck에서 카드 하나를 선택한다.
int index = (int)(Math.random() * CARD_NUM);
return pick(index);
}
void shuffle(){ //카드의 순서를 섞는다.
for(int n=0; n<1000; n++){
int i = (int)(Math.random() * CARD_NUM);
Card temp = c[0];
c[0] = c[i];
c[i] = temp;
}
} //Deck클래스의 끝
public static void main(String[] args){
Deck d = new Deck();
Card c = new Card();
d.shuffle();
Card c2 = d.pick(55);
}
1.4 단일 상속(single ingeritance)
- Java는 단일상속만을 허용한다.(C++은 다중상속 허용)
class TVCR extends Tv, VCR{ //이와 같은 표현은 허용하지 않는다.
//...
}
- 비중이 높은 클래스 하나만 상속관계로, 나머지는 포함관계로 한다.
class Tv{
boolean power; //전원상태(on/off)
int channel; //채널
void power() { power = !power;l ]
void channelup() { ++channel }
void channelDown() { --channel }
}
class VCR{
boolean power; //전원상태(on/off)
int counter = 0;
void power() { power = !power; }
void play(){ /*내용 생략*/ }
void stop(){ /*내용 생략*/ }
void rew(){ /*내용 생략*/ }
void ff(){ /*내용 생략*/ }
}
class TVCR extends TV{
VCR vcr = new VCR();
int counter = vcr.counter;
void play(){
vcr.play();
}
void stop(){
vcr.stop();
}
void rew(){
vcr.rew();
}
void ff(){
vcr.ff();
}
}
1.5 Object 클래스 - 모든 클래스의 최고 부모
- 부모가 정의 안된 클래스는 자동적으로 Object클래스를 상속받게 된다.
- 상속계층도의 최상위에는 Object 클래스가 위치한다.
- 모든 클래스는 Object클래스에 정의된 11개의 메서드를 상속받는다.
toString(), equals(Object obj), hashCode(), ...
class Tv{
//...
}
class CaptionTv extends Tv{
//...
}
▼
class Tv extends Object{
//...
}
class CaptionTv extends Tv{
//...
}
2. 오버라이딩(overriding)
2.1 오버라이딩이란?(overriding)
"부모클래스로부터 상속받은 메서드의 내용을 상속받는 클래스에 맞게 변경하는 것을 오버라이딩이라고 한다."
*override - vt. '~위에 덮어쓰다(overwrite).', '~에 우선한다.'
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
}
}
2.3 오버로딩 vs 오버라이딩
오버로딩(over loading) - 기존에 없는 새로운 메서드를 정의하는 것(new)
오버라이딩(overriding) - 상속받은 메서드의 내용을 변경하는 것(change, modify)
class Parent{
void parentMethod() {}
}
class Child extends Parent{
void parentMethod() {} //오버라이딩
void parentMethod(int i){} //오버로딩
void childMethod() {}
void childMethod(int i){} //오버로딩
void childMethod() {} //에러!!! 중복정의임
}
2.4 super - 참조변수
▶ this - 인스턴스 자신을 가르키는 참조변수, 인스턴스의 주소가 저장되어있음
모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재
▶ super - this와 같음. 부모의 멤버와 자신의 멤버를 구별하는데 사용.
class Parent{
int x=10;
}
class Child extends Parent{
int x=20;
void method(){
System.out.println("x=" +x);
System.out.println("this.x="+this.x);
System.out.println("super.x="+super.x);
}
}
class Parent{
int x=10;
}
class Child extends Parent{
void method(){
System.out.println("x="+x);
System.out.println("this.x="+this.x);
System.out.println("super.x="+super.x);
}
}
2.5 super() - 부모의 생성자(1/2)
- 자식클래스의 인스턴스를 생성하면, 자식의 멤버와 부모의 멤버가 합쳐진 하나의 인스턴스가 생성된다.
- 부모의 멤버들도 초기화되어야 하기 떄문에 자식 생성자의 첫 문장에서 부모의 생성자를 호출해야한다.
Object클래스를 제외한 모든 클래스의 생성자 첫 줄에는 생성자(같은 클래스의 다른 생성자 또는 조상의 생성자)를 호출해야한다.
그렇지 않으면 컴파일러가 자동적으로 'super();'를 생성자의 첫 줄에 삽입한다.
class Point{
int x;
int y;
Point(){
this(0,0);
}
Point(int x, int y){
this.x = x;
this.y = y;
}
}
▼
class Point extends Object{
int x;
int y;
Point(){
this.(0,0);
}
Point(int x, int y){
super(); //Object();
this.x=x;
this.y=y;
}
}
2.5 super() - 부모의 생성자(2/2)
Point3D(int x, int y, int z){
this.x=x;
this.y=y;
this.z=z;
}
▼
Point3D(int x, int y, int z){
super(); //Point()를 호출
this.x = x;
this.y=y;
this.z=z;
}
or
Point3D(int x, int y, int z){
//조상의 생성자 Point(int x, int y)를 호출
super(x, y);
this.z=z;
}
3 package 와 import
3.1 패키지(package)
- 서로 관련된 클래스와 인터페이스의 묶음.
- 클래스가 물리적으로 클래스파일(*.class)인 것처럼, 패키지는 물리적으로 폴더이다.
패키지는 서브패키지를 가질 수 있으며, '.'으로 구분한다.
- 클래스의 실제 이름(full name)은 패키지명이 포함된 것이다.
(String클래스의 full name은 java.lang.String)
-rt.jar는 Java API의 기본 클래스들을 압축한 파일
(JDK설치경로\jre\lib에 위치)
3.2 패키지의 선언
- 패키지는 소스파일에 첫 번째 문장(주석 제외)으로 단 한번 선언한다.
- 하나의 소스파일에 둘 이상의 클래스가 포함된 경우, 모두 같은 패키지에 속하게 된다.(하나의 소스파일에 단 하나의 public클래스만 허용한다.)
- 모든 클래스는 하나의 패키지에 속하며, 패키지가 선언되지 않은 클래스는 자동적으로 이름없는(unnamed) 패키지에 속하게 된다.
package com.javachobo.book;
public class Packagetest{
public static void main(String[] args){
System.out.println("Hello World!");
}
}
public class Packagedtest2 {}
3.3 import문
- 사용할 클래스가 속한 패키지를 지정하는데 사용.
- import문을 사용하면 클래스를 사용할 때 패키지명을 생략할 수 있다.
class importTest{
java.util.Date today = new java.util.Date();
}
▼
import java.util.*;
class ImportTest{
Date today = new Date();
}
- java.lang 패키지의 클래스는 import하지 않고도 사용할 수 있다.
String, Object, System, Thread
public static void main(java.lang.String[] args){
java.lang.System.out.println("Hello World");
}
3.3 import문의 선언
- import문은 패키지문과 클래스선언의 사이에 선언한다.
일반적인 소스파일(*.java)의 구성은 다음의 순서로 되어 있다.
① package문
② import문
③ 클래스 선언
- import문을 선언하는 방법은 다음과 같다.
import 패키지명.클래스명;
또는
import 패키지명.*;
package com.javachobo.book;
import java.text.SimpleDateFormat;
import java.util.*;
public class PackageTest{
public static void main(String[] args){
//java.util.Date today = new java.util.Date();
Date today = new Date();
SimpleDateFormat date = new SimpleDateFormat("yyyy/MM/dd");
}
}
3.3 import문의 선언예
- import문은 컴파일 시에 처리되므로 프로그램의 성능에 아무런 영향을 미치지 않는다.
import java.util.Calendar;
import java.util.Date;
import java.util.ArrayList;
▼
import java.util.*;
- 다음의 두 코드는 서로 의미가 다르다.
import java.util.*;
import java.text.*;
▼
import java.*;
- 이름이 같은 클래스가 속한 두 패키지를 import할 때는 클래스 앞에 패키지명을 붙여줘야 한다.
import java.sql.*; //java.sql.Date
import java.util.*; //java.util.Date
public class ImportTest{
public static void main(String[] args){
java.util.Date today = new java.util.Date();
}
}
제어자 | 대상 | 의 미 |
static | 멤버변수 | -모든 인스턴스에 공통적으로 사용되는 클래스변수가 된다. 클래스변수는 인스턴스를 생성하지 않고 사용 가능하다. 클래스가 메모리에 로드될 때 생성된다. |
메서드 | -인스턴스를 생성하지 않고도 호출이 가능한 static메서드가 된다. static메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다. |
class Statictest{
static int width = 200;
static int height = 120;
static { //클래스 초기화 블럭
//static변수의 복잡한 초기화 수행
}
static int max(int a, int b){
return a > b ? a : b;
}
}
제어자 | 대상 | 의 미 |
final | 클래스 | 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다. |
메서드 | 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다. | |
멤버변수 | 변수 앞에 final이 없으면, 값을 변경할 수 없는 상수가 된다. | |
지역변수 |
final class FinalTest{
final int MAX_SIZE = 10; //멤버변수
final void getMaxSize(){
final LV = MAX_SIZE; //지역변수
return MAX_SIZE;
}
}
class Child extends FinalTest{
void getMaxSize() {} //오버라이딩
}
public static void main(String[] args){
Card c = new Card("HEART", 10);
// c.NUMBER =5; //에러!!!
System.out.println(c.KIND);
System.out.println(c.NUMBER);
}
제어자 | 대상 | 의 미 |
abstract | 클래스 | 클래스 내에 추상메서드가 선언되어 있음을 의미한다. |
메서드 | 선언부만 작성하고 구현부는 작성하지 않은 추상메서드임을 알린다. |
[참고] 추상메서드가 없는 클래스도 abstract를 붙여서 추상클래스로 선언하는 것이 가능하기는 하지만 그렇게 해야 할 이유는 없다.
abstract class AbstractTest{ //추상클래스
abstract void move(); //추상메서드
}
4.6 접근 제어자(access modifier)
- 맴버 또는 클래스에 사용되어, 외부로부터의 접근을 제한한다.
접근 제어자가 사용될 수 있는 곳 - 클래스, 멤버변수, 메서드, 생성자
private - 같은 클래스 내에서만 접근이 가능하다.
default - 같은 패키지 내에서만 접근이 가능하다.
protected - 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.
public - 접근 제한이 전혀 없다.
4.7 접근 제어자를 이용한 캡슐화
접근 제어자를 사용하는 이유
- 외부로부터 데이터를 보호하기 위해서
- 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서
public static void main(String[] args){
Time t = new Time(12, 35, 30);
//System.out.println(t.toString());
System.out.println(t);
// t.hour = 13; 에러!!!
//현재시간보다 1시간 후로 변경한다.
t.setHour(t.Hour()+1);
System.out.println(t);
}
'JAVA > 개념' 카테고리의 다른 글
[JAVA] 05. OOP 1(객체 지향 언어) (0) | 2017.08.01 |
---|---|
[JAVA] 04. Array (배열) (0) | 2017.07.31 |
[JAVA] 03. 조건문, 반복문 (Control Statement) (0) | 2017.07.30 |
[JAVA] 02. 연산자(Operator) (0) | 2017.07.28 |
[JAVA] 01. 변수(Variable) (1) | 2017.07.28 |
댓글