본문 바로가기

Java/이론 정리

[JAVA SE – API _ 클래스변수와 클래스메소드 _ Singleton Pattern _ 상속 _ super _ 다형성 살펴보기]

3주차 (API / 클래스변수와 클래스메소드 / Singleton Pattern / 상속 / super / 다형성 )

API( application programming interface )

  • Pre written code의 일종
  • 크게 2가지(Core & extension) API로 나뉜다.

 

Core API : Sun에서 배포 ßà Extension API – Anonymous 가 만들어서 배포.

 

[실습]API Document 만들기

/***

|

| Date : 2010-03-15

| 이것은 API문서를 만드는 샘플입니다<br/>

*/

 

public class TestDoc{

//private로 Attribute를 하나 선언하고 이 값이 API Docu에서 보이는지 확인하기

private String attr;

/**첫번째 Method</br> A의 작업을 처리합니다.*/

 

public void methodA(){}

 

/**두번째 Method <br/>*/

public String methodB(){

return "a";

}

/** 3rd Method<br/> C processing*/

public void methodC(String str,int a){}

}

 

 

D:\SRC\0315\javadoc>javadoc *.java

Loading source file TestDoc.java...

Constructing Javadoc information...

Standard Doclet version 1.6.0_18

Building tree for all the packages and classes...

Generating TestDoc.html...

Generating package-frame.html...

(중간 생략)

Generating index.html...

Generating help-doc.html...

Generating stylesheet.css...

 

 

클래스 변수와 클래스메소드

 

10.1 Class Member를 사용하는 이유

 

이제까지는 Method를 객체마다 하나씩 생성하여 부여했다.

Ex)학생1에 getName(), 학생2에 getName()... 이런 식이라면

Stu.getName() & stu1.getName()….이런 식으로 할당되었지만

 

엄밀히 따지면 이들 Method의 역할은 모두 같은 것이므로 이들 Method를 인스턴스 객체 메소드로 두는게 아니라, Class Method로 선언하게 되면, 한번만 선언해서 사용하면 된다. 다시 말해 모든 객체들이 하나의 공통된 데이터나 기능을 가지면 이들을 Class Member로 두면 된다. 이를 위해서는 Static 변수로 선언하면 된다.

 

10.2 제한자 Static

 

특징

 

  • Class의 멤버로 객체와는 관계가 없다.
  • Static 멤버(Variable & Method)는 Class.멤버로 접근한다. -> 접근을 위해 객체생성이 필요 없다.
  • Static Method는 instance member에 직접 접근할 수 없다. 즉, Static Method는 Static Member만 호출 가능하다.

 

Ex) class ClassStatic{

int a;

static int b;

}

위 소스에서 a는 객체 소속이고, b는 클래스 소속이 된다. 부과적으로 예를 들어 객체가 100개가 있다고 가정하면 a는 100개가 된다. Stu1.a stu2.a stu3.a ….~ stu100.a로 접근하는 것이고 b의 경우 클래스 소속이기 떄문에 객체가 100개가 생성되어도 b 는 1개면 된다.

 

**메모리 살펴보기

 

Memory

Type

Comment

Stack

실행 Method의 Local 변수들이 저장되는 영역

(변수 선언줄이 JVM에 의해 읽혀질 때)

Heap

객체가 저장되는 영역

(객체가 생성자에 의해/ 생성되어지는 코드에 의해 메모리에 올라감)

Class Area

쉽게 클래스를 위한 녀석들이 저장되며, 크게 3가지로 나뉜다.

(Java Compile 시에 메모리에 올라감. 다시 말해 java *.java 명령어가 시작되면 가장먼저 Class Loading(=*.class 파일을 메모리에 올리는 것)이 되는데, 이때를 일컫는다. 그 외 다른 Area의 영역들에도 해당 값들이 올라간다.)

 

Area

Comment

Method Area

Class에 선언된 Method Code가 저장

Static Area

Class의 Static Member들이 저장

Constant Pool

Class에 선언된 상수를 저장.

 

(복습)

java의 실행은

1. Class Loading -> 2. Inspection -> 3. main() Method Execute)

 

** Static 변수(=Class 변수)

선언위치

Class Block 내에 선언되어야 하며 이때, static 제한자가 붙어야 한다.

Default 초기화 유무

(Static이나 Instance 변수는 존재, But Local은 없다. 無)

생명주기

Program Execute ~ Program Exit

 

용어정리

Instance Member Variable + Static Member Variable = Field 라고 부르기도 한다.

 

예제소스 StaticCount.java

/***

|

| Date : 2010-03-15

| Writer : DionysosJH™

| Subject : 10장 클래스 (변수와 메소드)

|

*/

 

public class StaticCount{

private int instanceCount; //instance member

private static int staticCount; //static member

 

public StaticCount(){

// 생성될 때 초기값 1을 갖도록 만들었다.

instanceCount++;

staticCount=instanceCount+staticCount;

}

public int getInstanceCount(){

return instanceCount;

}

 

public static int getStaticCount(){

return staticCount;

}

public static void main(String[] args){

StaticCount sc1=new StaticCount();

StaticCount sc2=new StaticCount();

StaticCount sc3=new StaticCount();

 

System.out.println("1번 객체 :" + sc1.getInstanceCount());

System.out.println("2번 객체 :" + sc1.getInstanceCount());

System.out.println("3번 객체 :" + sc1.getInstanceCount());

 

//Static Method는 아래와 같이 객체.메소드명이 아닌

클래스명.메소드명으로 호출한다.

System.out.println("StaticCount의 StaticCount값 : "+StaticCount.getStaticCount());

}

}

//Saving Name : StaticCount.java

 

Output Data

====================

1번 객체 :1

2번 객체 :1

3번 객체 :1

StaticCount의 StaticCount값 : 3

====================

결과값에서 확인할 수 있듯이

객체 소속인 Instance 멤버들은 각 객체 sc1, sc2,sc3 별로 instanceCount 변수를 가지고,

클래스 소속인 staticCount 변수는 Class에 소속되며 1개만 존재한다. 그렇기에 그 값이 공유되고, 예제에서 값이 누적되어 3이 도출된다.

부과적으로 클래스 변수의 값을 사용자가 초기화 해주지 않았음에도 값이 제대로 도출된 것을 통해 JVM에 의한 Default 초기화가 이루어 진다는 것도 확인할 수 있다.

 

**Static Block 살펴보기

= 실행블록으로 실행시점은 Class Loading시 실행된다.

= 역할은 Static 변수의 초기화(Initialization)에 사용된다. Argument는 올 수 없고, 그저 실행 구문만 올 수 있다. 다시 말해 Main Method가 실행되기 전에 연산을 통하거나, DB에서 정보를 가져오거나 등등의 선처리 작업을 수행할 수 있다.

Ex)

Static{

Static String domain;

}

 

(소스 추후 확인)

 

public class StaticCount{

 

//Static BLock 만들기

//Main 메소드를 지우고 컴파일을 해보면 Compile 오류가 나더라도 아래 static block은 실행되는 것을 확인 할 수 있는데 이를 통해 static 블록이 main Method 이전에 실행되는 것을 확인할 수 있다.

static{

System.out.println("static block1");

}

static{

System.out.println("static block2");

}

 

private int instanceCount; //instance member

private static int staticCount; //static member

 

public StaticCount(){

instanceCount++;

staticCount=instanceCount+staticCount;

}

public int getInstanceCount(){

return instanceCount;

}

public static int getStaticCount(){

 

//만일 static메소드에서 instance 메소드에 접근하려면 객체를 아래와 같이 생성 후 접근 가능하다

//StaticCount sc=new StaticCount();

//System.out.println(sc.instanceCount);

 

return staticCount;

}

public static void main(String[] args){

 

StaticCount sc1=new StaticCount();

StaticCount sc2=new StaticCount();

StaticCount sc3=new StaticCount();

 

System.out.println("1번 객체 :" + sc1.getInstanceCount());

System.out.println("2번 객체 :" + sc1.getInstanceCount());

System.out.println("3번 객체 :" + sc1.getInstanceCount());

 

//Static Method는 객체.메소드명이 아닌 클래스명.메소드명으로 호출한다.

System.out.println("StaticCount의 StaticCount값 : "+StaticCount.getStaticCount());

}

} 

static block1

static block2

1번 객체 :1

2번 객체 :1

3번 객체 :1

StaticCount의 StaticCount값 : 3

 

 

**Singleton(Design) Pattern

 

  • 1개의 Class에서 1개의 객체만 생성하도록 하라.
  • 기존 우리 방식에선 하나의 클래스에서 여러 개의 객체를 생성하여 만들었다면, 이 방법은 하나의 클래스에서 하나의 객체만을 만들어 사용하는데, 이(객체)를 다시 여러 객체가 참조하는 방식으로 중간 객체의 값이 바뀌면 END 노드의 객체들의 값도 변경된다.
  • SingleTon 설계 대상이 되는 객체는 Business Logic 객체이다. 즉, VO와 같이 값을 저장하기 위한 것이 아닌 계산을 위한 객체에 맞다.

     

  • SingleTone 설계 규칙

1 생성자를 private로 선언한다.

2. 객체를 저장할 static 변수를 만든다. 이때 객체는 Private으로 지정한다.

3. 2의 객체를 return하는 public get___ 메소드를 public static get____메소드를 사용한다.

 

SingletonClass.java

class SingletonClass{

 

private static SingletonClass instance;

private SingletonClass( ){} // private 생성자

 

// static getter

public static SingletonClass getSingleton( ){

if(instance == null)

instance = new SingletonClass();

return instance;

}

 

public void methodA(){

System.out.println("SingletonClass");

}

}

 

public class SingletonTest{

 

public static void main(String[] args){

 

SingletonClass sc1 = SingletonClass.getSingleton();

SingletonClass sc2 = SingletonClass.getSingleton();

System.out.println(sc1 + "," + sc2);

sc1.methodA();

}

} 

 

클래스의 상속 1 : 상속의 기본

상속(Inheritance)?!

객체가 다른 객체의 (Variable & Method) Member를 물려 받는 것.

이 때 Method 중 생성자의 경우 생성자 생성 규칙(=메소드명은 클래스명과 동일해야한다)에 위배되기 때문에 불가능하다.

(상속은 클래스 vs 클래스의 개념이 아닌 객체 vs 객체 Level)

 

장점

  • 상속을 통해 코드가 간결해진다.(재사용성)
  • 확장성

 

상속해주는 클래스

상속받는 클래스

Super

Sub

Parent

Child

상위

하위

기초

유도

 

추상화(Abstract)

구체적인 클래스에서 공통적인 분모들을 묶어 상위클래스를 만들어내는 것.

상위클래스에서 하위클래스로 올수록 해당 하위 클래스만이 가지는 특성을 가지게 된다. 그런 의미로 볼 때 상위 클래스는 하위 클래스보다 규모가 크다고 할 수 있다.

Ex)

동물

수컷-

암컷-

말라뮤트,진도,시츄..

고양이

수컷-

암컷-

샴,페르시아~~

사자

수컷-

암컷-

 

기린

수컷-

암컷-

 

코끼리

수컷-

암컷-

 

위 그림에서 살펴보듯 상위 클래스는 하위 클래스보다 크다.

 

상속을 다른 말로 is a 관계라고도 한다.

'하위 클래스 is a 상위클래스'라는 뜻으로 예를 들어 고양이는 동물이다. 냉장고는 가전제품이다. 등이 성립하므로 이들은 성립하지만, 동물은 고양이다. 가전제품은 냉장고이다. 등은 성립되지 않음을 확인할 수 있다.

 

참고적으로 'has a' 관계도 찾아보기! (졸려서 지금은 포기!! GG) has a 관계는 Whole-part관계라 한다.

또 use a 관계는 사용과 관련된 관계이다. go()

 

상속에 있어 자식이 부모클래스를 둘 이상 받을 수 있는 다중 상속과 부모클래스가 하나인 단일 상속으로 나뉠 수도 있다. 인터페이스 기법을 사용하지 않는 한, 자바에서는 클래스와 클래스에서는 단일 상속만을 지원한다. 인터페이스를 사용하지 않으면서 다중상속이 될 수 있도록 하기 위해선 일렬(=B가 A를 상속받고, C가 B를 상속받도록 한다.

A <- B ß C를 하게 되면 C 에서 B 뿐 아니라 A클래스의 멤버들도 사용이 가능하다. )로 상속을 받는다. 하지만 부모클래스의 멤버들이 이름이 중복될 시 애매함으로 결론적으로 자바는 다중상속을 하지 않는다.

 

상속을 사용하기 위한 문법

  • extends
     

    class 부모클래스{

    }

    class 자식클래스 extends 부모클래스{

    }

     

     

  • 코드적으로 부모클래스만 봐서는 자식클래스들을 알 수 없다. (= 자식클래스를 봐야 부모클래스를 알 수 있다.)
  • 같은 부모클래스를 가지는 자식클래스들 사이에서는 관계를 맺지 않는다.(단지 부모-자식관계만 성립한다.)

 

Super

Super 클래스 내지는 super 객체를 의미한다. 즉 상속에서 부모 클래스를 의미한다.

 

  1. Super([value1,value2,value3…..value(n)]
  • Super class(부모)에 정의된 생성자 호출
    • 생성자 구현부의 첫 구문으로 와야 한다.
    • ★ 생성자 구현부의 첫 구문에 this(), super()가 없으면 JVM이 묵시적으로 super(); 코드를 자동으로 삽입한다.
    • This()와 super() 모두 구현부의 첫 구문으로 와야 하기 때문에 이 둘이 동시에 사용될 수는 없다.
  1. Super. (= 부모객체를 의미)
  • Super Class 객체를 참조하는 인스턴스 (참조)변수로 JVM에 의해 자동으로 생성.
  • Ex)

class manager{

int id;

System.out.println(super.id);

}

위의 코드가 많이 생략되긴 했지만, 결론적으로 살펴보면 현 클래스의 변수명과 출력하고자하는 (부모클래스에 있는)변수명이 같을 때, 이를 명시해주기 위해 사용될 수 있다. 빈도수는 낮다.

 

또한 서로 패키지가 다르면서 상속관계를 받아와야 할 때, 사용된다.

Ex2)

Class Employee{

Protected String name;

}

 

<--------->

Class Manager Extends Employee{

Manager M=new Manager();

System.out.println(super.name);

}

뭐 이런 개념~*

 

 

ZooTest.java

/***

|

| Date : 2010-03-16

| Subject : Intertance Exam

| Contance : 부모 Animal 클래스를 상속받는 Cat & Dog 클래스를 만들고, Method를 상속받아보자.

*/

 

class Animal{

//동물들의 공통적인 속성인 name을 제한자 private를 사용하여 클래스변수로 선언

private String name;

//protected String name;

 

public void eat(){

System.out.println("먹는다");

}

public void sleep(){

System.out.println("잠잔다");

}

}

 

class Cat extends Animal{

public void cry(){

System.out.println("울어요");

}

}

/**아래 printName() 메소드를 실행해보면

---------- javac ----------

ZooTest.java:27: name has private access in Animal

System.out.println("고양이 이름 : " + name);

^

1 error

 

출력 완료 (0초 경과) - 정상 종료

 

와 같이 오류가 나는 것을 확인할 수 있는데 이를 통해 자식클래스에서 부모클래스의 private으로 선언된 변수에는 접근이 불가능함을 알 수 있다.

*/

public void printName(){

System.out.println("고양이 이름 : " + name);

}

/*

---------------------------------------------------------------------------------------------

(( 아래 괄호 부분은 정리 다시!!

고로, 부모클래스에서 private가 아닌 protected 로 선언하게 되면 상속관계의 하위 클래스가 부모클래스의 변수에 접근이 가능해진다.

 

이러한 문제를 해결하기 위해서는 super를 사용해야 한다.

즉 super를 사용하여 자식클래스에서 부모클래스의 Attribute에 접근이 가능하다.

---------------------------------------------------------------------------------------------

*/

 

class Dog extends Animal{

public void bark(){

System.out.println("짖는다");

}

}

 

public class ZooTest{

public static void main(String[] args){

Cat cat1=new Cat();

cat1.cry();

cat1.eat();

cat1.sleep();

System.out.println("\n");

 

Dog dog1=new Dog();

dog1.bark();

dog1.eat();

dog1.sleep();

}

}

 

/**

상속은 'Class vs Class'가 아닌 'Object vs Object'인데 이에 관한 설명을 하자면

우선적으로 cat과 animal 클래스 사이에 상속관계가 되면,

코드상에서는 나오지 않지만 실제적으로 cat 과 animal 사이에 참조변수가 하나 생성된다.

위 소스에서 cat1.eat(); 이란 라인이 실행된다면

우선 cat1을 찾고 거기서 참조변수를 따라 animal에 접근 cat에 없는 eat() Method를 찾아 접근하게 된다.

 

부과적으로 super() 를 통해 부모클래스(슈퍼클래스)의 생성자들을 호출하기 때문에 가능하다.

프로그래머가 명시적으로 적든, JVM이 묵시적으로 사용하든 super()가 있기 때문에 부모클래스의 멤버들이 사용 가능한 것이다.

super()는 하위 클래스 객체가 슈퍼 클래스의 생성자를 호출할 때 사용된다.

 

*/ 

 

Employee.java

public class Employee{

String id;

String name;

int salary;

 

public Employee(String id, String name, int salary){

this.id=id;

this.name=name;

this.salary=salary;

}

 

//사원의 정보를 출력하는 메소드

public void getDetails(){

System.out.println("id:"+ id +"\n"+ "name: "+name+"\n" +"월급: " +salary);

}

}

Manager.java

public class Manager extends Employee{

String department;

 

//생성자 Manager를 생성할 때 인자값으로 ( id,name, salary,department )을 받는다.

public Manager(String id, String name,int salary,String department){

//부모의 생성자 호출

super(id,name,salary);

this.department=department;

}

}//Employee.java & EmployeeTest.java와 연동

 

* 만약 super(id,name,salary); 을 없애면

---------- javac ----------

Manager.java:14: cannot find symbol

symbol : constructor Employee()

location: class Employee

public Manager(String id, String name,int salary,String department){

^

1 error

--------------------------------

오류가 발생하게 된다.

Employee 클래스에서 명시적으로 Employee(String id, String name,int salary)생성자를 만들어주었는데 Manager.java에서 묵시적으로 super() 와 Match되지 않기 때문에 생기는 문제이다.

그러므로 Employee에서 Emplyee()를 습관적으로 만들어주는 것도 좋다.

EmployeeTest.java

class EmployeeTest{

public static void main(String[] args){

/* 아래 코드가 생략되어 있다.

public Manager(){

super()

}*/

Manager m=new Manager("1","2",100,"3");

//m.id="interitanceT";

//m.name="상속자";

//m.salary=10000;

m.getDetails();

}

} 

 

Method Overriding(메소드 재정의)

 

  • 부모 class에 정의한 Method를 자식 class에서 (Method의 구현부를) 재정의 하는 것

     

생성규칙

 
 
  1. Super class와 {Return type & argument List & 이름}이 동일
  2. 부모에 정의된 method보다 하위 method(overriding한 Method)의 접근 제한자의 범위가 넓거나 최소한 같아야 한다.
  3. Exception 관련 규칙.
  • 부모 Method가 throws 한 것만 throws 할 수 있다.
  • 부모 Method가 throws 한 것을 throws 안 할 수 있다.
 

| Date : 2010-03-16

| Subject : Intertance Exam

| Contance : 부모 Animal 클래스를 상속받는 Cat&Dog 클래스를 만들고, 메소드를 상속받아보자.

 

class Animal{

protected String name;

 

public void eat(){

System.out.println("먹는다");

}

public void sleep(){

System.out.println("잠잔다");

}

}

 

class Cat extends Animal{

 

/*새롭게 추가된 코드) Method Overring 기법 */

public void eat(){

System.out.println("고양이는 핥아 먹는다.");

}

/*

---------------------------

이에 따른 변경된 출력값

---------------------------

울어요

고양이는 핥아 먹는다.

잠잔다

 

 

짖는다

고양이는 핥아 먹는다.

잠잔다

 

public void eat(String 10){

System.out.println("고양이는 핥아 먹는다.");

return 10;

}

위 변경된 소스에서 처럼 부모클래스와 Argument 또는 return type 을

다르게 주게 되면 인식하지 못하고 부모클래스의 eat() 메소드를 실행하게 된다.

 

*/

 

public void cry(){

System.out.println("울어요");

}

}

class Dog extends Animal{

 

public void eat(){

System.out.println("고양이는 핥아 먹는다.");

}

 

public void bark(){

System.out.println("짖는다");

}

}

 

public class ZooTest{

public static void main(String[] args){

Cat cat1=new Cat();

cat1.cry();

cat1.eat();

cat1.sleep();

System.out.println("\n");

 

Dog dog1=new Dog();

dog1.bark();

dog1.eat();

dog1.sleep();

}

}

 

복습>

Compiler가 자동으로 만드는 객체

  1. 생성자
  2. This() , super()
  3. Java.lang.* 에 있는건 자동으로 import되어진다.
  4. Class 선언에 extends를 쓸 필요가 없다.-> extends object
  5. Method 내에서 this. 이나 super.은 생략 가능하다.

 

Method Overring 실습예제

public class Employee{

private String id;

private String name;

private int salary;

 

public Employee(String id, String name,int salary){

this.id=id;

this.name=name;

this.salary=salary;

}

 

//사원의 정보를 출력하는 메소드

public void getDetails(){

System.out.println("id:"+ id +"\n"+ "name: "+name+"\n" +"월급: " +salary);

}

} 

public class Manager extends Employee{

String department;

 

//생성자 : id,name, salary,department

public Manager(String id, String name, int salary, String department){

//부모의 생성자 호출

super(id,name,salary);

this.department=department;

}

 

//2010-03-17에 추가된 코드

public void getDetails(){

//System.out.println("id:"+ super.id +"\n"+ "name: "+super.name+"\n" +"월급: " +super.salary);

// private으로 변수를 제한하였기 때문에 바로 윗라인으론 출력이 안되고 아래와 같이 super의 출력메소드를 호출하여 사용하여야 한다.

super.getDetails();

 

System.out.println("부서:"+this.department);

// 이 코드의 경우 변수명이 겹치지 않기 때문에 this. 나 super. 을 굳이 꼭 사용할 필요는 없다.

}

//Employee.java & EmployeeTest.java와 연동

} 

class EmployeeTest{

public static void main(String[] args)

{

Manager m=new Manager("DionysosJH","secret",10000000,"R&D");

m.getDetails();

}

} 

 

다형성(Polymorphism)

 

  • 부모 Type의 (참조)변수에 자식 객체를 할당하는 것.

     

    Ex

 

 

 

 

 

 

 

 

 

Animal an=new animal();

An=new dog()

An=new cat()

An=new human();

 

다른 예로 강제형 변환에서 ' double d= ' 에 다른 타입의 값을 입력할 수 있는 것도 Casting Mechanism이 있기 때문이다. 이런 것처럼 상속에 있어 생성자가 자식객체를 호출할 때, 이때, 부모 객체도 Heap에 같이 올라 오기 때문에 가능하다.

 

 

class animal{

Eat();

}

class dog{

Eat();

Bark();

}

Animal a=new dog();

a.eat();

a.bart();

부모 클래스(animal)과 자식클래스(dog)을 만들었다. 자식 클래스 dog에는 다형성을 통해 eat() method를 쓰고 있다.

위 코드를 실행해보면 Compile이 오류나는 것을 확인할 수 있다.이는

  1. Animal class를 참조하는 객체 a에 dog 클래스의 생성자를 호출하여 넣는다.
  2. a.eat()을 실행시 jvm은 a가 Animal클래스를 참조하므로 Animal 로 가서 eat() Method를 찾는다. 찾아보면 있으니까 ok
  3. 위와 같이 a.bark()를 Animal 클래스에서 찾아보니 없다. 그러므로 오류가 난다.

컴파일은 변수 type 것 체크

실행은 객체 것을 실행한다. 뭐 이건 이해안가지만 …위에 글적느라 설명 못듣고… 뭐 결론적으로 위 코드는 컴파일이 안되기 떄문에 실행결과값을 볼 수 없다.(논리적으론 가능하나, 우선적으로 컴파일안되는… )

 

위의 문제를 해결하기 위해서 즉,

a.bark()가 안 되는건 컴파일러가 a가 animal 참조객체이기 때문이고 animal에는 bark()가 없는 것이다.

Animal a=new dog();

a.bark();

dog d=(dog)a;

d.bark();

 

이런 식으로 강제 형변환을 수행하면 된다.

 

다형성 사용예)

  • 배열에 적용하게 되면, 해당 배열에 한 데이터 타입에 국한되지 않고, 다른 여러 데이터 타입들을 같이 넣을 수 있다.
  • Argument에 적용하는 것.

    Ex)

    Void go(Animal a){

    a.eat();

    }

     

    Zootest 코드 정리해서 넣기!!!

    예제

    /***

    |

    | Date : 2010-03-17

    |

    */

     

    // 입력 문자열에 더해줄 포맷을 생성

    class Format{

    //return 및 argument Type이 String인 getFormet 메소드 생성

    public String getFormet(String message){

    String returnMessage="----------------------------------------";

    returnMessage=returnMessage+"\n"+message;

    returnMessage=returnMessage+"\n"+"----------------------------------------";

    return returnMessage;

    }

    }

     

    class AstariskFormat extends Format{

    public String getFormet(String message){

    String returnMessage="***********************************";

    returnMessage=returnMessage+"\n"+message;

    returnMessage=returnMessage+"\n"+"***********************************";

    return returnMessage;

    }

    }

     

    class EqualFormat extends Format{

    public String getFormet(String message){

    String returnMessage="==============================";

    returnMessage=returnMessage+"\n"+message;

    returnMessage=returnMessage+"\n"+"==============================";

    return returnMessage;

    }

    } 

    /***

    |

    | Date : 2010-03-17

    */

     

    class Word{

    public void print(String message, Format format){

    String printMessage=format.getFormet(message);

    System.out.println(printMessage);

    }

    }

     

    public class WordUser{

    public static void main(String[] args){

    Word word=new Word();

    Format f=new Format();

    AstariskFormat af=new AstariskFormat();

    word.print("출력할 내용: Hello", f);

    word.print("출력할 내용: Hello", af);

    }

    } 

    ----------------------------------------

    출력할 내용: Hello

    ----------------------------------------

    ***********************************

    출력할 내용: Hello

    ***********************************

     

 

instanceof 연산자

= 객체와 클래스를 비교하여 준다.

[문법]

객체 instanceof type(클래스명)

a instanceof Animal à a 객체가 Animal 클래스의 객체이냐?

Return type이 Boolean이다. (여기서 Boolean 값은 무조건 True이어야 한다.)

전제로 이 둘이 상속관계이거나 실제 Type일 때만 가능하다.

다시 말해

Class A{

A a=new A();

} 이거나

 

Class B extends A{

B a=new B();

} 일 때 위 조건이 성립한다는 것이다.

 

위 어디선가 설명했지만, 이들이 사용되는 예는

void go(Animal an){

an.eat();

 

dog d=(dog)an;

d.bark();

}

라는 구문이 있을 때 기본적으로 컴파일은 되고, 실행시 될 확률과 안될 확률이 있다. 실행이 되기 위해서는 argument an에 dog의 객체가 들어올 경우이고, 실행이 안될 경우는 dog의 객체가 아닌 다른 객체(하나의 예로 cat)가 들어오게 되면 이는 실행이 되지 않는다.

이건 부모-자식 지간에는 상속관계로 묶어지지만, 형제 지간(?!)은 맺어지지 않는 자바의 특성이다. 즉

Class Dog extends Animal 과 class Cat extends Animal이 되었다고 해서 Cat과 Dog이 관계를 맺는 것은 아니라는 것이다!!

 

 

/***

|

| Date : 2010-03-16

| Writer : DionysosJH™

| Subject : Intertance Exam

| 부모 Animal 클래스를 상속받는 Cat & Dog 클래스를 만들고, 메소드를 상속받아보자.

| 부과적으로 상속은 'Class vs Class'가 아닌 'Object vs Object'인데 이에 관한 설명을 하자면

*/

 

class Animal{

 

protected String name;

 

public void eat(){

System.out.println("먹는다");

}

public void sleep(){

System.out.println("잠잔다");

}

}

 

class Cat extends Animal{

 

/*새롭게 추가된 코드) Method Overring 기법 */

public void eat(){

System.out.println("고양이는 핥아 먹는다.");

}

public void cry(){

System.out.println("울어요");

}

}

class Dog extends Animal{

 

public void eat(){

System.out.println("고양이는 핥아 먹는다.");

}

 

public void bark(){

System.out.println("짖는다");

}

}

 

public class ZooTest{

public static void main(String[] args){

Cat cat1=new Cat();

cat1.cry();

cat1.eat();

cat1.sleep();

System.out.println("\n");

 

Dog dog1=new Dog();

dog1.bark();

dog1.eat();

dog1.sleep();

System.out.println("-----다형성 테스트-----------");

polymorphismTest();

}

public static void polymorphismTest(){

Animal an1=new Animal();

Animal an2=new Dog();

Animal an3=new Cat();

//animla 타입 변수 animal,dog,cat 세계의 다른 객체를 할당 -<< 다형성

an1.eat();

an2.eat();

an3.eat();

an1.sleep();

an2.sleep();

an3.sleep();

 

//an2.bark(); <---아래 형변환을 통해 해결한다.

/*

an2가 Animal 참조 객체이므로 bark()를 Animal에서 찾기 때문에 없다고 나온다.

 

ZooTest.java:119: cannot find symbol

symbol : method bark()

location: class Animal

an2.bark();

^

1 error

 

==============

이를 해결하기 위해서는 강제 형 변환을 실시한다.

*/

Dog d=(Dog)an2;

d.bark();

 

System.out.println("----------HeterogeneousTest----------");

HeterogeneousTest();

 

System.out.println("\n----------다형성을 이용한 Argument----------");

Animal a=new Animal();

Dog dog=new Dog();

Cat cat=new Cat();

go(a);

go(dog);

go(cat);

}

 

//다형성 2번 예제 argument 이용

public static void go(Animal an){

an.eat();

an.sleep();

//2010-03-17 Start

boolean b=an instanceof Dog;

if(b){

Dog d=(Dog)an;

d.bark();

 

}else if(an instanceof Cat){

Cat c=(Cat)an;

c.cry();

}

//2010-03-17 End

System.out.println("가게 하다");

}

 

public static void HeterogeneousTest(){

//상위 클래스 배열 타입에 하위 클래스들의 객체들을 넣는 것.

//다형성을 배열에 적용한 것

Animal [] an=new Animal[5];

an[0]=new Animal();

an[1]=new Dog();

an[2]=new Cat();

an[3]=new Dog();

an[4]=new Dog();

 

an[0].eat();

an[1].eat();

an[2].eat();

 

//an[3].bark();

/**역시 마찬가지로 오류가 나므로 매나 똑같이~*

---------- javac ----------

ZooTest.java:153: cannot find symbol

symbol : method bark()

location: class Animal

an[3].bark();

^

1 error

아래의 코드로 해결해야 한다.

*/

 

Dog d=(Dog)an[3];

d.bark();

 

System.out.println("====반복문 실행====");

for (int idx=0;idx<an.length ;idx++ ) {

an[idx].eat();

}

 

System.out.println("\n For ~ Each문을 통한 출력\n");

for (Animal a: an ){

a.eat();

}

}

}

 

/**

상속은 'Class vs Class'가 아닌 'Object vs Object'인데 이에 관한 설명을 하자면

우선적으로 cat과 animal 클래스 사이에 상속관계가 되면,

코드상에서는 나오지 않지만 실제적으로 cat 과 animal 사이에 참조변수가 하나 생성된다.

위 소스에서 cat1.eat(); 이란 라인이 실행된다면

우선 cat1을 찾고 거기서 참조변수를 따라 animal에 접근 cat에 없는 eat() 메소드를 찾아 접근하게 된다.

 

부과적으로 super() 를 통해 부모클래스(슈퍼클래스)의 생성자들을 호출하기 때문에 가능하다.

프로그래머가 명시적으로 적든, JVM이 묵시적으로 사용하든 super()가 있기 때문에 부모클래스의 멤버들이 사용가능한 것이다.

super()는 하위 클래스 객체가 슈퍼 클래스의 생성자를 호출할 때 사용된다.

*/

 

 

프로그램 에서의 관리의 개념

  • Create(추가)
  • Review or Research?!(조회)
  • Update(수정)
  • Delete(삭제)

 

>> final 제한자

=마지막의 의미로 변경이 안된다. 변수(모든변수, 메소드, class 어디에든 붙을 수 있다.

 

ex)

final class A = 상속이 불가능한 A 클래스로 abstract의 반대 개념.

final void methodA() =오버라이딩이 불가능한 메소드로 정의할 때 사용.

final 변수 = 변수의 값을 변경할 수 없도록 한다. (=변수의 상수화), 값이 한번 할당되면 바꿀 수 없다.

 

Final 변수의 값 초기화 시점

Instance variable

  • 선언하면서 할당(명시적 초기화) or
  • 생성자에서 할당(생성자 수행)

Class Variable

  • 선언하면서 할당

Local Variable

  • 사용 전에 할당.

Final 변수 이름 규약

  • 모두 대문자로
  • 단어+단어일 때는 _로 구분

Final 변수 이름 규약 : 모두 대문자로 & 단어+단어일 때는 _로 구분