다형성이란 하나의 메소드나 클래스가 있을 때 이것들이 다양한 방법으로 동작하는 것을 의미한다.



 카페 > JAVA, JAVASCRIP..  zeroDay

 http://cafe.naver.com/jjdev/2991. 다형성(polymorphism)

 

다형성이란 상위 클래스의 타입의 참조변수로 하위클래스의 객체를 참조하는 것을 말한다.

※ 추상클래스나 인터페이스도 상위클래스에 해당한다. 

추상클래스를 상속한 클래스의 객체나 인터페이스를 구현한 클래스의 객체를 상위 추상클래스 형이나 

인터페이스 형 변수로 참조 가능하다. 추상클래스와 인터페이스는 뒤에 단원에서 설명한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person
{
int x;
}
 
class Student extends Person
{
int y;
}
 
 
Person p = new Student(); // 다형성
// p가 참조할 수 있는 멤버는 Student가 다 가지고 있기에 문제가 없다.
Student s = new Person(); // X compile error!
// s가 참조할 수 있는 멤버가 Person보다 많기에 에러 발생
cs



2. 참조변수의 형변환

 

(데이터타입) : 형변환 연산자

ex) (String)s, .....

※ 형변환 연산자는 기본타입에서도 사용가능하다.  ex) (int)2.3 



모든 참조변수는 변수에 객체의 참조값이 들어오기에 자식타입(서브타입)으로 강제 형변환이 가능하다. 

강제형변환을 하여도 변수가 변한 것이지 객체자체가 변화한 것이 아니므로 실행시 예외가 발생할 수도 있다. 

1
2
3
4
Person p = new Person();
Student s = (Student)p; // p변수를 강제로  Student로 형변환 , 정상적으로 컴파일
s.y = 10;
// 실행시 에러! , s가 가르키는 실체 객체는 new Person()으로 만들어 졌기때문에 y가 없다.
cs



3. 매개변수의 다형성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Car{
    void powerOn(){}
}
 
class Spark extends Car{
    void powerOn(){
        System.out.println("스파크 시동켜다");
    }
}
 
class Morning extends Car{
    void powerOn(){
        System.out.println("모닝 시동켜다");
    }
}
 
class Ray extends Car{
    void powerOn(){
        System.out.println("레이 시동켜다");
    }
}
cs


운전자는 위의 차들을 움직이기 위해서는 오버로딩된 메서드 3개가 필요하다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Driver{
 
    void carMove(Spark spark){
        spark.powerOn();
    }
 
    void carMove(Morning morning){
        morning .powerOn();
    }
 
    void carMove(Ray ray){
        ray.powerOn();
    }
}
cs


하지만 다형성을 이용하면 다음과 같이 하나의 메서드로 가능하다.


1
2
3
4
5
6
class Driver
{
    void carMove(Car car){
        car.powerOn();
    }
}
cs


Car형 car변수는 Spark, Morning, Ray 객체를 다 참조 가능하다. 

다형성을 활용하면 새로운 하위클래스 형식을 프로그램에 추가 하더라도 코드를 굳이 바꿀 필요가 없다. 




※ 메모리 생성 형태로 다형성 이해하기



다형성을 의미론적으로 설명하면 위의 예에서 "학생은 사람이다"와 "사람은 학생이다"에서 문맥상 앞의 문장이 맞는 표현이다.

(부모형에 자식형이 들어가는게 맞는 표현이다) 



그럼 메모리에 생성되는 형태로는 어떻게 설명되는가?



다음과 같은 상속관계의 클래스가 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A{
    int x;
    int y;
    void testOne(){}
    void testTwo(){}
}
 
 
class B extends A{
    int y;
    int z;
    void testTwo(){}
    void testThree(){}
}
cs



new A() 실행시 메모리에 참조될 수 있는 A객체의 멤버는 다음과 같다.(최상위 클래스인 Object클래스의 멤버는 당연히 참조되지만 이 설명에서는 생략한다 )


1
2
3
4
this.x
this.y
this.testOne()
this.testTwo()
cs



new B() 실행시 메모리 참조될 수 있는 B객체의 멤버는 다음과 같다.

(하위클래스의 생성자에서 상위 클래스의 생성자를 호출한다고 생성자 부분에서 설명했다. 그 의미를 알고 있다면 아래의 결과가 이해하기 쉬울것이다)


1
2
3
4
5
6
7
8
super.x
super.y
super.testOne()
super.testTwo()
this.y
this.z
this.testTwo()
this.testThree()
cs



B클래스의 내부에서는 super, this키워드를 이용하여 동일한 x변수나 testTwo()메서드를 구분하여 호출이 가능하겠지만, B클래스 아닌 다음과 같은 예에서는 B클래스의 객체에 대해서 super나 this같은 키워드 사용이 불가하다.


1
2
3
4
5
6
7
8
class C{
    B b = new B();
    // b.super.testTwo(); //이런 형태의 호출은 자바 문법에서는 제공하지 않는다. 
    // b.this.testTwo(); //이런 형태의 호출은 자바 문법에서는 제공하지 않는다.  
    // 만약에 위와 같은 형태의 표현을 자바언어가 지원했다면 자바언어가 좀더 유연해졌을까?
    // 아님 그냥 좀더 배우기 힘든 언어가 되었을까?
    b.testTwo();
}
cs
 

그럼 위의 testTwo()는 둘중 어떤 메서드를 호출하는가? 

자바언어는 다른클래스에서 객체를 생성후 멤버메서드 호출시 this.메서드가 있으면 this.메서드를 호출하고, 

없을때만 super.메서드를 호출한다. -> 오버라이딩 



A a = new B(); 되는 이유는 a변수가 참조할 수 있는 x, y, testOne(), testTwo()를 

new B()객체(super.x, super.y, this,y, super.testOne(), super.testTwo()(존재는 하지만 오버라이딩때문에 외부에서는 호출불가능) ,

this.testTwo())가 다 가지고 있기에 가능한 것이고(다형성), 

B b = new A();의 경우는 b변수가 참조할 수 있는 x, y, z, testOne(), testTwo(), testThree()를 

new A()객체가 다 가지고 있지 않기때문에 오류가 발생한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A{
    int x = 1;
    void test(){System.out.println("A실행")}
}
 
class B extends A{
    int x = 2;
    void test(){System.out.println("B실행")};
}
 
class MainTest{
    public static void main(String[] args){
        A a = new B();
        System.out.println(a.x); // 1출력 - 변수는 오버라이딩이 안된다. 부모참조변수로 호출하면 super.x가 호출된다.
                                    // 변수는 오버라이딩 대상이 아니니 부모와 동일한 이름의 변수는 사용금지!
        a.test(); // "B실행"출력 -  메서드 오버라이딩에 의해 super.test()가 아닌 this.test()가 호출된다.  
}
cs

 


 - 부모와 동일한 이름의 변수이름을 사용하는 것 -> 잘못된 습관

- 부모와 동일한 이름의 메서드 이름을 사용하는 것(구현기능이 유사할때) -> 잘된 습관(객체지향의 오버라이딩을 사용하는 습관)

 


 

* 다형성은 객체지향언어에서 가장 중요한 부분이여서 설명하는데 조심스럽기도 하지만, 특성상 "글 보다는 말", "말 보다는 그림"으로 설명하는 것이 이해가 빠른데... 글로 표현할려니 힘이 드네요 ㅠㅠ...  

'Java' 카테고리의 다른 글

final 클래스/final 메소드  (0) 2017.02.25
instance of 연산자  (0) 2017.02.25
오버라이딩  (0) 2017.02.25
상속  (0) 2017.02.25
캡슐화  (0) 2017.02.25

상속은 상위 클래스의 기능을 하위 클래스에게 물려주는 기능이다. 

그렇다면 하위 클래스는 상위 클래스의 메소드를 주어진 그대로 사용해야 할까? 

만약 그래야 한다면 제약이 상당할 것이다. 이런 제약을 벗어나려면 하위 클래스가 

부모 클래스의 기본적인 동작방법을 변경할 수 있어야 한다. 

이런 맥락에서 도입된 기능이 메소드 오버라이딩(overriding)이다.

상속 시간의 예제를 살펴보자. 이 예제는 클래스 Calculator의 

기본적인 동작 방법을 상속 받은 SubstractionableCalculator에 빼기 기능을 추가하고 있다. 

이것은 상위 클래스의 기능에 새로운 기능을 추가한 것이다. 

만약 상위 클래스에서 물려 받은 메소드 sum을 호출했을 때 아래와 같이 

그 결과를 좀 더 친절하게 알려줘야 한다면 어떻게 해야할까?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Calculator {
    int left, right;
 
    public void setOprands(int left, int right) {
        this.left = left;
        this.right = right;
    }
 
    public void sum() {
        System.out.println(this.left + this.right);
    }
 
    public void avg() {
        System.out.println((this.left + this.right) / 2);
    }
}
 
class SubstractionableCalculator extends Calculator {
     
    public void sum() { //
        System.out.println("실행 결과는 " +(this.left + this.right)+"입니다.");
    }
     
    public void substract() {
        System.out.println(this.left - this.right);
    }
}
 
public class CalculatorDemo {
    public static void main(String[] args) {
        SubstractionableCalculator c1 = new SubstractionableCalculator();
        c1.setOprands(1020);
        c1.sum();
        c1.avg();
        c1.substract();
    }
}
cs


메소드 sum이  SubstractionableCalculator에 추가 되었다. 

실행결과는 c1.sum이 상위 클래스의 메소드가 아니라 하위 클래스의 메소드 sum을 실행하고 있다는 것을 보여준다. 

하위 클래스 입장에서 부모 클래스란 말하자면 기본적인 동작 방법을 정의한 것이라고 생각할 수 있다. 

하위 클래스에서 상의 클래스와 동일한 메소드를 정의하면 부모 클래스로부터 물려 받은 

기본 동작 방법을 변경하는 효과를 갖게 된다. 기본동작은 폭넓게 적용되고, 

예외적인 동작은 더 높은 우선순위를 갖게하고 있다. 이것은 공학에서 일반적으로 발견되는 규칙이다. 

이것을 메소드 오버라이딩(overriding)이라고 한다.



오버라이딩의 조건


overriding을 하기 위해서는 메소드의 리턴 형식이 같아야 한다.

오버라이딩을 하기 위해서는 아래의 조건을 충족시켜야 한다.

메소드의 이름

메소드 매개변수의 숫자와 데이터 타입 그리고 순서

메소드의 리턴 타입

위와 같이 메소드의 형태를 정의하는 사항들을 통털어서 메소드의 서명(signature)라고 한다.

 

https://opentutorials.org/course/1223/6090

'Java' 카테고리의 다른 글

instance of 연산자  (0) 2017.02.25
다형성  (0) 2017.02.25
상속  (0) 2017.02.25
캡슐화  (0) 2017.02.25
접근제어자  (0) 2017.02.25

상속의 기본적인 특성


기존의 정의된 클래스에 메소드와 변수를 추가하여 새로운 클래스를 정의하는것이다.

상속을 받은 클래스의 인스턴스에는 상속의 대상인 클래스의 정의된 메소드와 변수가 존재한다.


상속관계에서 상속을 받은 클래스를 가르켜 '하위클래스(sub class)'

상속의 대상이 된 클래스를 '상위클래스(super class)' 라 부른다.


상위클래스로부터 상속받는 하위클래스가 확장(extends) 하는것이다.


상속의 장점은 코드의 중복을 줄일수있고 , 유지보수 또는 재활용이 용이하다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//상위클래스 (super class)
public class A {
    int a = 0;
    public static void A(){
        
    }
}
 
//하위클래스 (sub class)
public class B extends A {
}
 
public class MainDemo {
    public static void main(String[] args){
        
        B b = new B();
        b.A(); 
        //상속을받음으로써
        //B클래스에 정의되지않은 메서드인A();를 호출이가능하다.
 
        System.out.println(b.a);
        //상속을받음으로써
        //B클래스에 선언되지않은 변수 a를 사용할수있다.
    }
}
 
cs
 



상속과 생성자


하위클래스의 생성자 내에서는 반드시 상위클래스의 생성자가 호출되어야 한다.

만일 상위클래스의 생성자를 호출할수없는 구조로 하위 클래스의 생성자가 정의된다면,

하위클래스의 인스턴스 생성은 불가능하다.



1
2
3
4
5
6
public class B extends A {
    
    public B(){
        super();
    };
}
cs


하위클래스 내의 생성자에는 상위클래스를 가르키는 키워드인 super 를 사용해

상위클래스의 생성자를 호출하고있다. 이부분은 생략해도 자동으로 삽입된다.




1
2
3
4
5
6
7
8
9
10
package java01;
 
public class A extends Object { //extends Object생략
    int a;
    
    public A(){
        super(); //상위클래스 생성자 호출 
        a=0;
    }
}
cs


 

자바의 모든 클래스는 상위클래스가 있어야한다 상위클래스가 없는경우 

자동으로 Object 클래스를 상속받는다. 코드는 생략되있다.




'Java' 카테고리의 다른 글

다형성  (0) 2017.02.25
오버라이딩  (0) 2017.02.25
캡슐화  (0) 2017.02.25
접근제어자  (0) 2017.02.25
static  (0) 2017.02.25

캡슐화


캡슐화는 데이터와 데이터를 처리하는 기능(메소드)를 하나의 캡슐처럼 묶는것이다.

객체외부에서는 내부의 데이터를 접근할수 없고 외부에서의 접근이 허용하도록 정의된

세팅이나 게팅 메서드를 통해서 접근할수 있다.


캡슐화의 장점

객체 내부의 메서드가 정보은닉이되어 오류발생이 적다.

인터페이스가 간결해진다.


캡슐화가 필요한 이유

외부에서 조작하거나 접근하면 안되는 데이터가있을경우에 캡슐화를 사용해 접근을 막는다.


ex 물건을 판매하는 프로그램을 작성할때 가격이나 수량을 외부에서 접근해 조작할수있는경우나

수량같은 메서드를 통해 상호작용을통해 변경을해야하는 변수가 상호작용없이 외부에서 조작되면안되는경우

'Java' 카테고리의 다른 글

오버라이딩  (0) 2017.02.25
상속  (0) 2017.02.25
접근제어자  (0) 2017.02.25
static  (0) 2017.02.25
생성자  (0) 2017.02.25

접근제어 지시자는 접근의 허용 범위를 제한하는 용도로 사용이 된다.

접근제어 지시자는 public private protected 세가지가있다. 아무런 선언도 하지않는경우까지포함하여

총 네가지의 접근제어 선언이 가능하다.접근제어자를 사용하는 이유는

마치 은행이 누구나 접근 할 수 있는 창구와 관계자외에는 출입이 엄격하게 통제되는 금고를 구분하고 있는 이유와 같다.


public

public으로 선언이되면 어디서든 접근가능한 인스턴스 변수 및 메서드가 된다.


private

외부에서 인스턴스변수에 직접 접근하는것을 차단한다.

private가 선언되면 해당변수가 선언된 클래스 외부에서는 접근이 불가능해진다.

private가 선언이되면 해당 메소드나 변수의 클래스가 접근할수있는 유일한 수단이 된다.


default 

접근제어자를 선언하지 않는경우 이러한형태의 선언을 디폴트 선언 이라하며

default로 선언된 인스턴스변수 및 인스턴스메소드는 동일 패키지 내에서의 접근을 허용한다.

클래스가 디폴트일경우에 생성자도 디폴트생성자가 자동으로 선언되고

퍼블릭클래스일경우에 생상자도 퍼블릭생성자가 자동으로 선언된다.


protected

protected는 상속을 받는 클래스의 접근을 허용하는 지시자이다.

상속으로 인해 접근제어자가 protected로 선언된 변수는 상속된 클래스의 변수가되어

상속받는클래스는 상속하는 클래스의 변수에 접근이 가능해진다.



 publicprotecteddefaultprivate
같은 패키지, 같은 클래스허용허용허용허용
같은 패키지, 상속 관계허용허용허용불용
같은 패키지, 상속 관계 아님허용허용허용불용
다른 패키지, 상속 관계허용허용불용불용
다른 패키지, 상속 관계 아님허용불용불용불용




'Java' 카테고리의 다른 글

상속  (0) 2017.02.25
캡슐화  (0) 2017.02.25
static  (0) 2017.02.25
생성자  (0) 2017.02.25
메소드 오버로딩(overloading)  (0) 2017.02.25

static 변수


static 변수는 하나만 존재하여 인스턴스간에 공유가 된다.


static 으로 선언된 변수는 메모리 공간에 하나만 존재하며,

어디서나 접근이 가능한 변수이다.

단어디서나 접근이 가능하려면 static 변수도 public 으로 선언되어야 한다.


static 변수가 초기화되는 시점은 JVM에 의해서 클래스가 메모리 공간에 올라가는 순간이다.

때문에 static 변수를 생성자를 통해서 초기화해서는 안된다

생성자를 통해 초기화를 하면 인스턴스가 생성될 때마다 새로운 값이 대입되게 된다.


static 변수는 static 블럭에서 초기화 하는것이 세련된 문법이다.


static 메소드


static 변수와 마찬가지로 static 메소드가 삽입된 클래스의 모든 인스턴스로부터 접근이 가능하다.

인스턴스를생성하지 않아도 static 메소드를 호출할수 있다.

static 메소드는 인스턴스 변수에 접근이 불가능하다.


static은 상태가 존재하지 않는클래스 / 인스턴스 생성의 가치가 없는 클래스에 사용하는것이 적합하다.


'Java' 카테고리의 다른 글

상속  (0) 2017.02.25
캡슐화  (0) 2017.02.25
접근제어자  (0) 2017.02.25
생성자  (0) 2017.02.25
메소드 오버로딩(overloading)  (0) 2017.02.25

  

생성자

 

자바의 인스턴스 생성시에는 반드시 생성자가 호출되어야 합니다. 


생성자는 인스턴스 생성시 딱 한번 호출되는 메소드로써 

인스턴스 변수의 초기화를 목적으로 정의되는 메소드이다.

 

생성자가 되기 위해서는 다음의 조건을 갖춰야한다

-클래스의 이름과 동일한 이름의 메소드

-반환형이 선언되어 있지 않으면서,반환하지 않는 메소드


클래스에는 반드시 생성자가 존재해야 한다 따라서 프로그래머가 생성자를 삽입하지 않으면

자바 컴파일러가 생성자를 대신 삽입해주는데 이렇게 삽입되는 생성자를 디폴트생성자 라한다 

매개변수가 있는 생성자가 있을 때는 자동으로 기본 생성자를 만들어주지 않는다.

따라서 매개변수가 있는 생성자가 있을시에는 기본생성자를 추가해줘야 한다.

 

생성자는 private으로 선언되면 클래스 내부에서만 호출이가능하기때문에

일반적으로 default와 public으로 선언이 된다.

생성자는 멤버변수에 대입되는 값이 없으면 int 타입일경우 0 객체타입을경우 null 로 초기화한다.

'Java' 카테고리의 다른 글

상속  (0) 2017.02.25
캡슐화  (0) 2017.02.25
접근제어자  (0) 2017.02.25
static  (0) 2017.02.25
메소드 오버로딩(overloading)  (0) 2017.02.25
메소드 오버로딩 overloading

매개변수의 숫자에 따라서 같은 이름의, 서로 다른 메소드를 호출한다.
이름은 같지만 시그니처는 다른 메소드를 중복으로 선언 할 수 있는 방법을 
메소드 오버로딩(overloading)이라고 한다.

-- 매서드 오버로딩의 조건
- 메서드의 이름이 같아야 한다.
- 매개변수의 개수 또는 타입이 달라야 한다.
- 매개변수는 같고 리턴타입이 다른 경우는 오버로딩이 성립되지 않는다.
  (리턴타입은 오버로딩을 구현하는데 아무런 영향을 주지 못한다.

메소드 오버로딩 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Addressbook 
{
    public static void main(String[] args)
    {
        person("홍길동",01011111111,1212,"aa@aa");
        person("홍길동",01011111111,1212);
        person("홍길동",0101111111);
    }
 
    public static void person(String name,int phoneNum,int birth,String mail)
    {
        //이름 전화번호 생일 메일을 출력하는 메소드
        System.out.println("이름 : "+name);
        System.out.println("전화번호 : "+phoneNum);
        System.out.println("생일 : "+birth);
        System.out.println("이메일 : "+mail);
    }
    
    public static void person(String name,int phoneNum,int birth)
    {
        //이름 전화번호 생일을 출력하는 메소드
        System.out.println("이름 : "+name);
        System.out.println("전화번호 : "+phoneNum);
        System.out.println("생일 : "+birth);
        
    }
    public static void person(String name,int phoneNum)
    {
        //이름 전화번호를 출력하는 메소드
        System.out.println("이름 : "+name);
        System.out.println("전화번호 : "+phoneNum);
        
    }
 
}
 
cs


'Java' 카테고리의 다른 글

상속  (0) 2017.02.25
캡슐화  (0) 2017.02.25
접근제어자  (0) 2017.02.25
static  (0) 2017.02.25
생성자  (0) 2017.02.25

+ Recent posts