Link Search Menu Expand Document

Inheritance(수평적구조VS수직적구조)

상속 -> 클래스의 설계(행위적인 측면)

Dog와 Cat이라는 클래스를 설계할 경우 모두 비슷한 성질(이름, 나이, 종)을 갖고 비슷한 행동(먹다)을 한다.

이러한 클래스를 설계하는 방향은 크게 두 가지가 있다.

  • 수평적 설계

서로 비슷한 객체에 대하여 코드의 중복이 발생하고 새로운 요구사항에 대한 코드의 수정이 불가피하므로 관리하기가 어렵다.

  • 수직적 설계(계층화, 상속구조)

수평적 설계의 단점을 극복하여 확장을 쉽게 할 수 있지만 코드가 복잡해진다.

super class(상위, 부모): 추상화, 보편화, 일반화, 개념화

sub class(하위, 자식): 세분화, 상세화, 구체화, 구상화

  • 소스 코드가 담겨있는 .java 파일을 타인에게 제공하지 않고 바이트 코드가 담겨있는 .class 파일만으로 타인이 개발할 수 있도록 하기 위해서는 어떻게 해야할까?

상속 개념

public class A extends B 와 같은 형식으로 A가 B를 상속받을 수 있다.

Object: Java의 모든 클래스의 최상위 클래스로 상속을 받지 않는 객체는 Object를 상속받는다.

super(): 자식의 생성자에서 부모의 생성자를 호출. 부모 객체가 먼저 만들어져야 하므로 따로 입력하지 않아도 자동으로 호출됨.

ex. Animal 클래스를 부모로 갖는 Dog 클래스를 호출할 경우…

  1. Dog 클래스 생성자에 의하여 Animal 클래스의 생성자가 호출되고
  2. Animal 클래스 생성자에 의하여 Object 클래스의 생성자가 호출된다.

재정의(Override)

Override(재정의)

  • 상속관계에서 상속받은 하위 클래스가 상위 클래스의 동작을 수정하는 것
  • 부모 클래스에 있는 메소드를 자식 클래스에서 재정의하는 것
  • 호출할 메소드가 실행 시점(런타임)에서 결정되는 동적 바인딩
    • static 메소드는 컴파일 시점에 메모리에 올라가기 때문에 오버라이딩 될 수 없다!
  • Override를 통해 부모 클래스를 가지고 자식 클래스에 접근할 수 있다.

나보다 부모가 먼저야!

상속관계에서 객체생성 방법

직접 생성 Dog d = new Dog(); -> 부모 클래스를 이용하지 않는 방식

간접 생성 Animal d = new Dog(); -> 하위 클래스의 동작 방식을 모를 때, class(실행) 파일만 있고 java(소스) 파일이 없는 경우

부모 자식간 형변환이 된다.

Upcasting(자동형변환)

  • 자식 클래스의 객체가 부모 클래스의 객체로 형변환되는 것을 말한다.
Animal d = new Dog();

위의 코드를 보면 부모 클래스 Animal 타입인 d가 자식 클래스 Dog 객체를 가리키고 있다.

Downcasting(강제형변환)

  • Upcasting과 반대로 자신의 고유한 특성을 잃은 서브 클래스의 객체를 다시 복구시켜주는 것을 말한다. 즉, upcasting된 객체를 원상태로 되돌리는 것이다.
Animal r = new Cat(); // upcasting
// r.night(); -> error
Cat c = (Cat)r; // downcasting
c.night();
  • . 연산자는 캐스팅 연산자보다 우선순위가 높으므로 캐스팅과 메소드 호출을 동시에 할 경우 괄호를 이용해야 한다.
  • 원래의 객체가 아닌 다른 서브 클래스로 downcasting 할 경우 ClassCastException이 발생한다.
  • Upcasting에서는 부모 클래스에서 구현한 메소드만을 호출할 수 있기 때문에, 자식 클래스에서 구현한 메소드를 호출해야 할 경우 upcasting된 객체를 downcasting으로 복구하여 메소드를 호출하여야 한다.

이러한 형변환은 OOP의 원리 중 다형성(polymorphism)과 연관이 있다.

리모콘 너무 좋은데(다형성 이론)

Polymorphism(다형성)

  • 상속관계에 있는 클래스에서 상위 클래스가 동일한 메시지로 하위 클래스들을 서로 다르게 동작시키는 객체지향 원리(개념)
  • 하위 클래스의 동작 방식을 알 수 없어도 상위 클래스를 통해 하위 클래스를 구동시킬 수 있다.

너무 좋아 좋아! 다형성의 활용

1. 다형성 이론의 전제조건(부모 클래스를 잘 활용하라)

  • 상속관계가 되어야 한다.
  • 객체 생성을 upcasting으로 할 것 (상위 클래스가 하위 클래스에게 메시지를 보내야 하므로)
  • 하위 클래스가 반드시 재정의(override)해야 한다.
  • 동적 바인딩을 통해 실현된다. 이는 프로그램의 속도를 떨어뜨리는 원인이 된다.

2. 다형성 활용 방법

  1. 다형성 인수(데이터 이동)
Dog d = new Dog();
display(d);
Cat C = new Cat();
display(c);

public static void display(Animal r) {
	r.eat();
    if (r instanceof Cat) {
        ((Cat)r).night();
    }
}

Animal의 하위 클래스인 Dog와 Cat을 display의 매개변수로 받을 수 있다

  1. 다형성 배열 (서로 다른 하위 클래스를 하나의 배열에 담을 수 있다)
Animal[] r = new Animal[2];
r[0] = new Dog();
r[1] = new Cat();
r[0].eat();  // 개처럼 먹다.
r[1].eat();  // 고양이처럼 먹다.
((Cat)r[1]).night();  // 밤에 눈에서 빛이 난다. -> downcasting

추상클래스(일부 다형성 보장)

public abstract class Animal{ // 추상클래스
	public abstract void eat(); // 추상메소드
	public void move() { // 구현메서드
		System.out.println("무리를 지어서 이동한다.");
	}
}
  • 위의 코드와 같이 abstract 구문을 이용하여 추상클래스를 구현할 수 있다.

  • 하위 클래스에서 추상메소드를 재정의하지 않으면 예외가 발생한다.

  • 인터페이스와 달리 추상클래스에는 구현메소드를 정의할 수 있다.

인터페이스(100% 다형성 보장)

public interface RemoCon{ // 인터페이스
	public abstract void chUp(); // 추상메소드
	public void chDown();
	public abstract void internet();
}
  • 인터페이스는 추상클래스와 다르게 구현메소드를 가질 수 없다.

부모가 있어서 너무 좋아!

추상클래스와 인터페이스(다형성을 보장하기 위함)

상위 클래스를 추상클래스나 인터페이스로 만들어야 다형성을 보장(재정의를 반드시 해야 됨) 할 수 있다.

공통점

  • 다형성을 보장하기 위하여 등장
  • new를 이용하여 인스턴스를 생성할 수 없다.
  • 하위 클래스에 의해 구현되어야 한다. (override: 재정의 필수)
  • 부모(상위) 클래스의 역할로 사용한다(upcasting으로 객체를 생성).
  • 추상 메소드를 가진다.

abstract class(추상클래스)

  • 서로 기능이 비슷한 클래스의 공통부분을 묶을 때 사용
  • 구현 메소드와 추상 메소드를 함께 가질 수 있다.
  • 50% 디자인(설계), 50% 구현
  • extends 키워드 사용

interface(인터페이스)

  • 서로 기능이 다른 클래스의 공통부분을 묶을 때 사용
  • 100% 추상 메소드로 이루어지므로 구현 메소드를 가질 수 없다.
  • 100% 디자인(설계), 규약
  • implements 키워드 사용
  • Java는 단일상속만을 지원하는 것이 원칙이지만 인터페이스는 다중상속 형태를 지원한다.
  • 추상 메소드와 final static 변수(상수)만을 멤버로 가질 수 있다.

인터페이스(규약)와 JDBC의 관계

  • JDBC(Java DataBase Connectivity): JDBC는 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API이다.

  • Java 개발자는 Java에서 제공하는 JDBC 인터페이스를 통하여 Oracle, MySQL, MSSQL 등의 데이터베이스에 동일한 메서드를 이용하여 접근할 수 있다. 따라서, 밴더 별로 데이터베이스 접속방법, CRUD 동작방법 등이 다르지만 개발자는 구현 내용에 대하여 알 필요가 없다.
  • DBMS와 통신을 담당하는 Java 클래스를 JDBC 드라이버라고 한다.

인터페이스의 상속관계

  1. 인터페이스와 인터페이스의 상속관계

    public interface A{
    	public void m();
    }
       
    public interface B extends A{
    	public void z();
    }
       
    public class X implements B{
    	public void m() {
    	}
       	
    	public void z() {
    	}
    }
    

클래스가 여러 개의 인터페이스를 상속받았을 경우 모든 메소드를 구현해야 한다.

  1. 다중상속관계에 있는 클래스 구조
public class Dog extends Animal implements Pet, Robots

클래스는 단일 상속만 가능하지만 인터페이스는 다중 상속이 가능하다.

Object 클래스는 신이야!

Object 클래스

모든 클래스의 root 클래스

  • 상속 관계에서 최상위 클래스 (기본적으로 extends Object가 생략되어 있음)
  • Object 클래스를 잘 활용하면 프로그램을 유연하게 만들 수 있다.

Object 클래스를 이용한 객체 생성

Object obj = new A();
A a = (A)obj;
a.display();
System.out.println(obj.toString());

toString()

  1. 재정의를 안 했을 경우 번지 출력
  2. 재정의를 했을 경우 재정의된 메소드 실행

Object 클래스의 활용

  1. 다형성 인수: 부모 클래스를 매개변수로 받는 메소드를 만들어 다형성을 보장한다.
  2. 다형성 배열: 각각의 공간에 타입이 다른 클래스를 저장할 수 있다.

package(패키지)가 뭐에요?

package(패키지)

  • 기능이 비슷한 클래스를 모아서 관리하기 쉽게 하기 위해
  • package 외부에서 접근하는 것을 막을 때 사용

package 외부에서 특정 클래스에 접근하는 방법

public class TPC33{
    public static void main(String[] args){
        kr.inflearn.MyClass my = new kr.inflearn.MyClass();
    }
}
import kr.inflearn.*;

public class TPC33{
    public static void main(String[] args){
        MyClass my = new MyClass();
    }
}

default 접근 권한

  • package 내부에 있는 클래스에게는 public
  • package 외부에 있는 클래스에게는 private

Java에서 제공해주는 API 접근 및 활용

java.lang package는 default package로 클래스를 만들면 자동으로 import된다.

String 클래스는 java.lang 패키지에 포함되어 있기 때문에 따로 import하지 않아도 사용 가능하다.

객체를 만드는 것도 중요하지만 기존에 존재하는 객체 사용법을 익히는 것도 중요하다.

문자열(String)이 객체라고요?

String 클래스

Java에서 문자열은 쌍따옴표(“ “)로 감싸면 된다.

Java에서 문자열을 저장하는 기본 자료형(ex. int, char, float)은 없다.

문자열은 여러 가지 조작을 할 수 있기 때문에 별도의 클래스로 자료형(java.lang.String)을 만들어 두었다.

그래서 Java에서 문자열은 책, 영화, 회원처럼 객체로 취급된다.

문자열 생성방법

  1. new로 생성
String str1 = new String("APPLE");
String str2 = new String("APPLE");

이렇게 생성된 String 객체는 Heap Area에 저장되고 str1, str2는 각각 메모리 상의 다른 주소를 가리킨다.

  1. 문자열 상수로 생성
String str3 = "APPLE";
String str4 = "APPLE";

이렇게 생성된 String 객체는 Literal Pool에 저장되고 str1, str2는 메모리 상의 같은 주소를 가리킨다.

  • Literal Pool: 문자열 상수(객체)가 생성되는 메모리 영역

내가 만든 최초 API

배열처럼 동작하는 클래스 만들기(IntArray)

API를 사용할 경우 배열의 구체적인 동작 방식([] 기호 사용 등)을 몰라도 배열을 사용할 수 있다.

IntArray의 한계점: int형 데이터만 배열에 담을 수 있다. -> ArrayList라는 API를 사용하여 문제 해결

ArrayList 흉내내기(Object[])

배열처럼 동작하는 클래스 만들기(ObjectArray)

내가 만든 API(10%)Java에서 제공해주는 API(100%)
길이 제한 있음길이 제한 없음 (기본 길이는 10)

크기에 상관 없이 객체를 저장하기(List)

ArrayList에 책(BookDTO) 3권을 저장하고 출력하기

ArrayList는 add(), get(), size() 등의 메소드를 가진다.

  • add() 메소드는 upcasting으로 동작한다.
List list = new ArrayList();
list.add(new BookDTO("Java", 21000, "영진", 590));
  • get() 메소드는 downcasting으로 동작한다.
BookDTO b = (BookDTO)list.get(0);

ArrayList에는 서로 다른 타입의 객체를 저장할 수 있지만 실무에서 이러한 방식으로 객체를 저장하는 경우는 없다고 봐도 좋다. 그래서 ArrayList<BookDTO>와 같은 형식으로 ArrayList에 넣는 자료형을 제한하는데 이를 제네릭(generic)이라고 한다.

제네릭을 사용하면

  • 형변환이 필요없고 타입안정성이 보장된다.
  • 코드의 재사용성이 높아진다.

Wrapper 클래스란?

기본자료형을 객체자료형으로 사용할 수 있도록 만들어 놓은 자료형으로 포장 클래스라고도 한다.

기본자료형객체자료형사용 예
intInteger1new Integer(1)
floatFloat23.4fnew Float(23.4f)
charCharacter'A'new Character('A')
booleanBooleantruenew Boolean(true)
  • 변수에 1을 저장하는 방법 2가지
int a = 1; // Case 1
Integer b = new Integer(1); // Case 2
int v = b.intValue();
  • 기본자료형을 Object[] 배열에 저장할 경우
Object[] obj = new Object[3];
obj[0] = new Integer(1); // obj[0] = 1;은 안되나?
obj[1] = new Integer(2);
obj[2] = new Integer(3);
  • Boxing과 Unboxing
Integer a = 1; // Boxing -> Integer a = new Integer(10);
int b = new Integer(10); // Unboxing -> int b = new Integer(10).intValue();

Boxing은 기본자료형을 객체자료형으로 바꾸는 것이고, Unboxing은 객체자료형을 기본자료형으로 바꾸는 것이다. Boxing과 Unboxing 모두 컴파일러에 의하여 자동으로 수행될 수 있다.

학습정리(객체지향 3대 특징)

객체지향 프로밍의 3대 특징

  1. 정보은닉(Information Hiding)
  2. 상속(Inheritance)
  3. 다형성(Polymorphism)

Message polymorphism(다형성)

상속 관계에 있는 클래스에서 상위 클래스가 동일한 메시지로 하위 클래스들을 서로 다르게 동작시키는 객체지향 원리(개념)

다형성 이론의 전제 조건

  1. 상속관계가 되어야 한다.
  2. 객체생성을 upcasting으로 해야 한다.
    • 상위 클래스가 하위 클래스에게 메시지를 보내야 하므로
    • upcasting이 되면 downcasting을 할 수 있다.
  3. 하위 클래스가 반드시 재정의(override)해야 한다.
  4. 실행 시점에서 사용할 메서드가 결정되는 동적 바인딩을 통해 실현된다. 이는 프로그램의 속도를 떨어뜨리는 원인이 된다.

추상클래스와 인터페이스의 공통점

  1. 다형성을 보장하기 위해서 등장
  2. new 를 이용하여 객체를 생성할 수 없다.
  3. 하위 클래스에 의해 구현되어야 하고 재정의가 필수적이다.
  4. 상위 클래스의 역할로 사용된다. (upcasting으로 객체를 생성)
  5. 추상 메소드를 가진다.