클래스 Object와 Wrapper 클래스

Object class

  • 클래스 Object는 Java에서 모든 클래스의 superclass
  • Java의 모든 클래스는 이미 equals와 toString 메서드 등을 가지고 있음
  • class Object의 member method
    • equlas, toString, getClass, hashCode()
  • toString method는 사용자가 원하는 결과를 출력하도록 Override를 해주어야 함
  • Object 클래스의 equals 메서드의 매개변수는 Object 타입
    • 매개변수로 제공된 객체와 자기 자신의 동일성을 검사
      • 값을 비교하는 것이 아님
    • 따라서 원하는 값의 비교를 해주기 위해서는 역시 Override 해주어야 함

Wrapper class

  • Java에서 primitive type 데이터와 non-primitive type 데이터(객체)는 근본적으로 다르게 처리됨
  • 때로 primitive type 데이터를 객체로 만들어야 할 경우가 있음
    • 이럴 때, Integer, Double, Character 등의 Wrapper class를 이용
int a = 20;
Integer age = new Integer(a);
int b = age.intValue();  // b becomes 20

// 데이터 간 형변환
String str = "1234";
int d = Integer.parseInt(str);  // d becomes 1234
  • Autoboxing과 Unboxing
Object[] theArray = new Object[100];
theArray[0] = 10; // 컴파일러가 자동으로 10을 Integer 객체로 변환해줌(autoboxing)
int a = (Integer)theArray[0]; // theArray[0]에 저장된 걱은 Integer 객체이지만 컴파일러가 자동으로 정수로 변환(unboxing)


'Software Convergence > Java' 카테고리의 다른 글

다형성: Polymorphism  (0) 2018.11.05
static과 접근제한자  (0) 2018.10.19
상속의 단점과 Strategy Pattern  (0) 2018.09.03
Generic 자료형 실습  (0) 2018.07.12
instanceof / encapsulation  (0) 2018.07.04

다형성: Polymorphism

  • Super class 타입의 변수가 Sub class 타입의 객체를 참조할 수 있다!
  • 예시) Notebook class가 Computer class를 상속 받고 있다고 가정
Computer computer = new Notebook("Bravo", "Intel", 4, 240, 2/4, 15)
  • Computer 타입의 변수 computer가 Notebook 타입의 객체를 참조하고 있음!

  • 다음의 예를 생각해보자
  • 가정) Computer와 Notebook class는 모두 toString method를 지니고 있음
System.out.println(compter.toString());
  • 위 예에서의 toString은 두 class 중 어느 class의 method를 호출하게 될까?
  • 답은 Notebook class의 toString !
    • 즉, 동적 바인딩(dynamic binding)이 일어남

      • Runtime 중에 참조 객체를 결정
    • cf. Computer class의 toString을 호출하는 경우, 정적 바인딩
      • 컴파일러가 참조 객체를 결정


'Software Convergence > Java' 카테고리의 다른 글

Object 클래스와 Wrapper 클래스  (0) 2018.11.13
static과 접근제한자  (0) 2018.10.19
상속의 단점과 Strategy Pattern  (0) 2018.09.03
Generic 자료형 실습  (0) 2018.07.12
instanceof / encapsulation  (0) 2018.07.04

static 그리고 접근제한자

static

  • static 멤버는 class 안에 실제로 존재
    • 즉, object의 선언 없이 사용 가능한 멤버
public class Test{
    static int s = 0;
    int t = 0;

    public static void print1(){
        System.out.println("s = " + s);
//      System.out.println("t = " + t);
//      non-static member 접근 불가
    }

    public static void print2(){
        System.out.println("s = " + s);
        System.out.println("t = " + t);
    }
}
  • Java에서의 프로그램은 class들의 집합이기 때문에 main 함수 역시 class 내에 존재해야 함
    • 하지만 class의 객체 생성 없이 main method는 실행되어야 하기 때문에 항상 static으로 선언되어야 함
  • static 멤버 변수의 접근 방법?
    • 'object명'. 과 같이 해도 정상작동하는 경우 많으나, 엄격한 compile 규칙을 따른다면 틀린 것
    • 따라서 class에 속하는 멤버이므로, '클래스명'. 과 같이 접근하는 것이 정석
public class Test {
    static int s = 10;
    int t = 0;
    
    public static void print1() {
        System.out.println("s = " + s);
    }
    
    public void print2() {
        System.out.println("s = " + s);
        System.out.println("t = " + t);
    }
    
    public static void main(String[] args) {
        Test test1 = new Test();
        test1.t = 100;
        test1.print2

        // static 멤버 접근 방법
        Test.s = 100;
        Test.print1();
    }
}
  • static 멤버의 용도
    • main method
    • 상수 혹은 클래스 당 하나만 유지하고 있으면 되는 값
      • ex) Math.PI, Systemo.out
    • 순수하게 기능만으로 정의되는 method
      • ex) Math.abs(k), Math.sqrt(n), Math.min(a, b)



접근 제어: public, private, default, protected

  • public: 클래스 외부에서 접근이 가능
  • private: 클래스 내부에서만 접근 가능
  • default: 동일 패키지에 있는 다른 클래스에서 접근 가능
  • protected: 동일 패키지의 다른 클래스와 다른 패키지의 하위 클래스에서도 접근 가능

데이터 캡슐화

  • 모든 데이터 멤버를 private으로 만들고 필요한 경우 public한 get/set method를 제공
  • 객체가 제공해주는 method를 통하지 않고서는 객체 내부의 데이터에 접근할 수가 없음
    • 함부로 데이터를 접근하거나, 수정할 수 없음
  • 이것이 data encapsulation 혹은 information hiding


'Software Convergence > Java' 카테고리의 다른 글

Object 클래스와 Wrapper 클래스  (0) 2018.11.13
다형성: Polymorphism  (0) 2018.11.05
상속의 단점과 Strategy Pattern  (0) 2018.09.03
Generic 자료형 실습  (0) 2018.07.12
instanceof / encapsulation  (0) 2018.07.04

상속의 단점과 Strategy Pattern

추상 클래스와 인터페이스

추상 클래스

  • 추상 클래스는 클래스의 일종
  • 상속 받은 정보를 부모 클래스로부터 Look-up 하여 살펴봐야 하기 때문에 인터페이스 보다 비싼 연산
  • 정수 / 멤버 / 정의되지 않은 메소 / 정의된 메소드를 지닐 수 있음
  • 메소드와 멤버를 어느 접근제한자로든 설정할 수 있음
  • 추상 클래스를 상속 받는 서브 클래스는 반드시 상속 받은 abstract method를 정의해주어야 함
    • cf) 추상 클래스 역시 다른 추상 클래스를 상속 받을 수 있는데 이 때는 부모 추상 클래스의 abstract method를 반드시 정의해줄 필요는 없음
  • 서브 클래스는 한 번에 한 개의 추상 클래스만을 상속 받을 수 있음
  • abstract method를 정의할 때 자식 클래스는 해당 method의 접근 제한자 level을 같거나 혹은 더 낮게 재설정할 수 있음
abstract class MotorVehicle
{
    int fuel;

    int getFuel()
    {
        return this.fuel;
    }

    abstract void run();
}

class Car extends MotorVehicle
{
    void run()
    {
        print("Wrroooooooom");
    }
}


인터페이스

  • 인터페이스는 일종의 계약이자 빈 껍데기. method들의 코드가 아닌 몸체만 존재하는 패턴과 같은 것
  • 인터페이스는 단순히 이름들의 나열이기 때문에 아주 적은 CPU만을 소모. 따라서 Look-up 작업을 할 필요가 없음
  • 정수 / 정의되지 않은 메소드를 지닐 수 있음
  • 모든 메소드들은 public level로 정의되어야 함
  • 인터페이스는 부모 인터페이스를 extend할 수 있는데 이 때 부모 인터페이스의 method를 구현할 필요 없음
    • 인터페이스는 method 구현이 불가하기 때문
  • 서브 클래스는 한 번에 여러 개의 인터페이스를 사용할 수 있음
  • 인터페이스를 사용하는 서브 클래스는 반드시 method를 같은 접근 제한 레벨인 public으로 정의해주어야 함
interface MotorVehicle
{
    void run();

    int getFuel();
}

class Car implements MotorVehicle
{
    int fuel;

    void run()
    {
        print("Wrroooooooom");
    }

    int getFuel()
    {
        return this.fuel;
    }
}



상속의 단점

  • 상위 클래스 기능에 버그가 생기거나 기능의 추가/변경 등으로 변화가 생겼을 때 상위 클래스를 상속 받는 하위 클래스가 정상적으로 작동할 수 있을지에 대한 예측이 힘듬
    • 하위 클래스는 상위 클래스의 부분 집합이기 때문에
  • 상속 구조가 복잡해질 수록 그 영향에 대한 예측이 힘들어짐
  • 상위 클래스에서 의미 있었던 기능이 하위 클래스에서는 의미 없는 기능일 수 있음
  • 하위 클래스는 반드시 상위 클래스로부터 물려 받은 기능들을 제공해야 함 + 하위 클래스에서 기능들이 추가됨
    • 기능 확장에 따라 상위 클래스에서 파생된 클래스들이 많아지고, 그 규모가 커짐에 따라 일관성 있게 작성하지 않은 클래스들에 대한 이해도는 점차 복잡해지고 사용에 어려움이 생길 수 있음

Strategy Pattern

  • 알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 만듦

  • 일반적으로 서브 클래스를 만드는 방법을 대신하여 유연성을 극대화시키는 용도로 사용

  • Strategy Pattern에서 class의 행위와 그 알고리즘은 run time시 변경될 수 있음

  • Strategy pattern에서 우리는 다양한 strategy를 나타내는 객체들과 수행하는 행위가 strategy에 따라 달라지는 context 객체를 생성

  • Strategy 객체는 context 객체의 수행 알고리즘을 변경하는 역할 수행

  • 인터페이스 생성

public interface Strategy {
    public int doOperation(int num1, int num2);
}
  • 같은 인터페이스를 사용하는 concrete class들을 생성 (concrete class: 지니고 있는 method들이 모두 정의되어 있는 class)
public class OperationAdd implements Strategy{
    @Override
    public int doOperation(int num1, int num2){
        return num1 + num2;
    }
}

public class OperationSubstract implements Strategy{
    @Override
    public int doOperation(int num1, int num2){
        return num1 - num2;
    }
}

public class OperationMultiply implements Strategy{
    @Override
    public int doOperation(int num1, int num2){
        return num1 * num2;
    }
}
  • Context 클래스 생성
public class Context{
    private Strategy strategy;

    public Context(Strategy strategy){
        this.strategy = startegy;
    }

    public int executeStrategy(int num1, int num2){
        return strategy.doOperation(num1, num2);
    }
}
  • Strategy가 바뀔 때 마다의 변화를 보기 위해 main 함수에서 Context 클래스 사용해봄
public class StrategyPatternDemo{
    public static void main(String[] args){
        Context context = new Context(new OperationAdd());
        System.out.println("10 + 5 = " + context.executeStartegy(10, 5)); // 15

        context = new Context(new OperationSubstract());
        System.out.println("10 - 5 = " + context.executeStartegy(10, 5)); // 5

        context = new Context(new OperationMultiply());
        System.out.println("10 * 5 = " + context.executeStartegy(10, 5)); // 50
    }
}


'Software Convergence > Java' 카테고리의 다른 글

다형성: Polymorphism  (0) 2018.11.05
static과 접근제한자  (0) 2018.10.19
Generic 자료형 실습  (0) 2018.07.12
instanceof / encapsulation  (0) 2018.07.04
다형성(Polymorphism) / Object 클래스  (0) 2018.07.03
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
// Class의 Object를 정의되지 않은 일반 자료형으로 받음
public class Generic<T> {
    private T t;
    
    public T get() {
        return this.t;
    }
    
    public void set(T o) {
        this.t = o;
    }
    
    public static void main(String[] args) {
        
        // T가 String으로 치환됨
        Generic<String> test1 = new Generic<String>();
        test1.set("AlYAC");
        
        // T가 Integer로 치환됨
        Generic<Integer> test2 = new Generic<Integer>();
        test2.set(3);
    }
}
 
// E - Element, K - Key (in map), V - Value (in map)
// N - Number, T- Type
cs

Java Generic 실습1
: class명에 <T>의 추가를 통해 generic 하게 자료형을 받겠다는 것을 명시한다. main method에서 보이는 것과 같이 내가 원하는 자료형에 따라 유동적으로 다른 자료형을 가지는 객체를 생성할 수 있게 된다. 즉, <String>으로 넣게 되면 String 자료형의 객체를 만들게 되며, <Integer>는 Integer 자료형의 객체를 만들어 주게 된다. 
Generic 부에 들어가는 기호로는 관습적으로 하단의 주석과 같은 것들이 사용된다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Generic2 {
 
    public static <E> void testArray(E[] array) {
        for(E e : array) {
            System.out.println(e);
        }
    }
    
    public static void main(String[] args) {
        Integer[] arr = {1,2,3,4,5};
        testArray(arr);
        
        String[] arr2 = {"Java""C""C++""JSP"};
        testArray(arr2);
    }    
}
cs

Java Generic 실습2
: 배열을 받아 출력하는 testArray method에 각각 Integer와 String으로 구성된 배열을 넘긴다. 넘겨준 배열의 자료형은 다르지만, 이상 없이 method의 출력 기능을 수행함을 알 수 있다.
cf. method에 인자를 넘겨줄 때는 항상 'Integer', 'Character'와 같은 Wrapper 클래스로 전달해주어야 한다.


​​​- instanceof 연산자
개체가 특정 클래스의 인스턴스인지를 판단하여 boolean ​​값을 반환하는 연산자. 객체지향 프로그래밍에 있어 특정 인스턴스가 어떤 클래스의 인스턴스인지를 파악하여 해당 클래스만이 가지는 변수 혹은 메소드를 사용할 수 있도록 조건문에 걸어주는 식으로 사용될 수 있음



- encapsulation




ADT와 유사한 개념. Class를 생성함에 있어 설계자가 아닌 사용자에게는 Class가 어떻게 구성되었고, 작동하는지에 대한 이해 없이도 사용이 가능하도록 캡슐화하는 것. 따라서, Class는 일종의 Black box와 같다고 할 수 있음. 캡슐화를 통해 사용자는 Class가 가진 변수, 메소드만 알아도 사용 가능하게 됨.


'Software Convergence > Java' 카테고리의 다른 글

static과 접근제한자  (0) 2018.10.19
상속의 단점과 Strategy Pattern  (0) 2018.09.03
Generic 자료형 실습  (0) 2018.07.12
다형성(Polymorphism) / Object 클래스  (0) 2018.07.03
추상클래스와 인터페이스 / final  (0) 2018.07.02

- 다형성(Polymorphism)
부모 객체의 변수로 부모 객체를 상속 받는 자식 클래스의 인스턴스를 정의하는 것. 예를 들면, 직업이 부모 클래스. 직업이라는 부모 클래스를 상속받고 있는 것이 전사, 마법사, 도적 등의 클래스라고 하자. 이 때 우리는 Job job = new Wizard(); 혹은 Job job = new Warrior(); 등과 같이 부모 클래스 변수를 다양한 모습으로 정의할 수 있음. 이는 사용자 입력에 따라 부모 객체의 변수를 부모 클래스를 상속 받는 클래스 중 하나로 선정하는 것과 같이 사용이 가능

- Object 클래스
모든 클래스의 조상 클래스 격. 명시적으로 상속받지 않더라도 언어 내부에서 모든 클래스는 이 Object 클래스를 암시적으로 상속 받고 있음. 다형성의 성질 때문에 Object 클래스는 다른 클래스의 인스턴스로 변환이 가능한 것이 특징​




-> equlas 메소드의 매개변수로 Object 클래스를 받고 이를 Archer형태의 인스턴스로 변환 후, temp라는 Archer클래스의 인스턴스로 정의. 이 같은 변환이 가능한 이유는 Object 클래스가 Archer 클래스의 부모 클래스 중 하나이기 때문에 다형성의 적용이 가능한 것!


'Software Convergence > Java' 카테고리의 다른 글

static과 접근제한자  (0) 2018.10.19
상속의 단점과 Strategy Pattern  (0) 2018.09.03
Generic 자료형 실습  (0) 2018.07.12
instanceof / encapsulation  (0) 2018.07.04
추상클래스와 인터페이스 / final  (0) 2018.07.02

- 추상 클래스와 인터페이스의 차이
추상 클래스는 내부에 정의된 메소드와 추상 메소드의 혼합된 사용이 가능. 또한 상수의 정의도 가능. 일반 클래스의 상속과 같이 extends 키워드 사용.

인터페이스는 내부에 모두 추상 메소드와 상수만 존재해야 함. 정의된 메소드를 품을 경우, 에러 처리. 클래스와 달리 implements 키워드를 통해 사용.

인터페이스를 이용해 '다중 상속'의 활용 가능(실제 다중 상속은 아니며, 흉내내는 기능의 수행) -> 인터페이스는 개수의 제한 없이 implements 가능. 만약 서로 다른 인터페이스를 사용하는데 같은 추상 메소드 명이 존재한다면, 사용하는 클래스에서 하나의 메소드로 정의가 가능 !

추상 클래스와 인터페이스 모두 구체적 메소드의 정의 이전에 설계의 목적이 강하지만, 인터페이스의 경우 앞서 언급한 것과 같이 정의된 메소드를 애초에 담을 수 없기 때문에 추상 클래스보다 '설계'의 의미를 더 강하게 지님. 따라서 인터페이스를 통한 설계가 많이 선호되는 편.

- final 키워드
final 키워드는 '최종적으로 규정'한다는 의미를 지님.
변수에 final을 붙일 시, 변수를 상수화하여 더 이상 수정이 불가능한 메모리 공간으로 만든다는 것
메소드에 final을 붙일 시, 더 이상 overriding이 불가능한 메소드로 규정해주는 것
클래스에 final을 붙일 시, 상속이 불가능한 하나의 독립적인 클래스로 규정해주는 것


'Software Convergence > Java' 카테고리의 다른 글

static과 접근제한자  (0) 2018.10.19
상속의 단점과 Strategy Pattern  (0) 2018.09.03
Generic 자료형 실습  (0) 2018.07.12
instanceof / encapsulation  (0) 2018.07.04
다형성(Polymorphism) / Object 클래스  (0) 2018.07.03

+ Recent posts