Four Principles of Object-Oriented Programming
•
Encapsulation(캡슐화)
여러 클래스 간의 member variable과 method들을 함부로 접근하는 것을 방지하기 위해 꼭 필요한 것만 public으로 설정하고 그 이외의 것들은 private으로 유지한다.
•
Abstraction(추상화)
"interface"기능 : 이런식으로 구현한다는 명세는 존재하는데 그 내부는 실재로 그렇게 정의되어 있지 않는 것을 이야기 함.
유사하게 abstract classes라고 존재
•
Inheritance(상속)
두 객체간의 "is-a" 혹은 "has-a"관계를 가지게 하는 것을 의미하며
super class (parent class) vs sub class (child class)로 클래스를 나눈다.
이러한 개념을 예시로 들어 설명하자면 동물이 있다고 하면 개, 새, 말 등등등을 각각 클래스로 만들면 매우 번거롭고 관리도 어렵게 된다. 그래서 하나의 공통된 속성을 묶어 놓은 클래스를 만들어서 그 세부적인 클래스에 우리가 구현하고자 하는 동물들의 성질을 정의하는 것도 하나의 방법이다.
•
Polymorphism(다형성)
1.
static Polymorphism : 이름은 동일하지만 여러 메소드로 나뉘는 함수 오버로딩
2.
dynamic Polymorphism : 혹은 자식클래스에서 부모 클래스의 메소드를 새로 정의하는 함수 오버라이딩
Interface
Abstraction을 구현해주는 개념이 Interface라는 자바의 개념이다. 정의하기로는 극단적으로 동일한 목적 하에 동일한 기능을 보장하기 위함이다. Interface를 보기 위해서 우리가 다음과 같은 기능을 구현한다고 생각해 보자.
integer sequence(수열)가 있고 이 수열의 앞부터 n개까지의 평균을 내주는 프로그램이 있다고 하자. 이제 아래와 같은 메소드를 정의하려고 하자고 하자.
public static double average(IntSequence seq, int n);
Java
복사
위의 메소드는 인자로 클래스를 받는다. 이것을 인자로 제공해주기 위해 클래스를 정의하자.
class IntSequence{
private int i;
public boolean hasNext(){
return true;
}
public int next(){
i++;
return i;
}
}
Java
복사
이제 위의 클래스를 인자로 받는 메소드를 정의하여 보자
public static double average(IntSequence seq, int n){
int count=0;
double sum=0;
while(seq.hasNext() && count<n){
count++;
sum+=seq.next();
}
return count==0?0:sum/count;
}
Java
복사
이제 가정하기를 다양한 형태의 행렬을 출력하는 함수를 만든다고 해보자
그렇다면 당연하게도 정의된 함수만큼 클래스를 구현하여야만 할 것이며 함수도 같이 그만큼 정의를 해주어야 한다. 하지만 실재로 그렇게 하는 것은 그렇게 쉽지 않으며 동시에 기능의 차이도 존재하지 않는데 구지 이렇게 할 이유가 존재하지 않는다.
그래서 나온 것이 interface라는 개념이다.
이를 위해서 interface라는 키워드가 java에는 존재한다.
//class 대신에 interface라고 정의한다.
interface IntSequence{
//이렇게 메소드의 헤더부분만 정의한다. 내용은 존재하지 않는다.
boolean hasNext();
int next();
}
Java
복사
그런데 메소드에 접근제한자가 존재하지 않는 것 같지만 interface는 class와 다르게 public 이 default access modifier이다. 또한 동시에 abstract 라는 키워드가 붙게 된다.
interface IntSequence{
public abstract boolean hasNext();
public abstract int next();
}
Java
복사
그렇다면 사용은 어떻게 할까?
그것을 위해 클래스를 만들고 implements 명령어를 사용하여서 객체를 먹여주어야 한다.
class SquareSequence implements IntSequence{
private int i;
public boolean hasNext(){
return true;
}
public int next(){
i++;
return i*i;
}
}
Java
복사
그다음 함수에는 interface 클래스를 매개변수로 보내는 것이다.
SquareSequence squares = new SquareSequence();
double avg = average(squares, 100);
public static double average(IntSequence seq, int n){
int count=0;
double sum=0;
while(seq.hasNext() && count<n){
count++;
sum+=seq.next();
}
return count==0?0:sum/count;
}
Java
복사
이런식으로 SquareSequence을 인자로 넘기어 줄 수 있다.
또한 interface 클래스는 자신을 받고 있는 subtype class를 객체로 받을 수 있다. 이렇게 써야하는 이유는 다른 subtype class 변수는 동일한 subtype 클래스를 받을 수 없기 때문이다.
심지어 변수의 타입은 여전히 IntSequence이다.
IntSequence squares = new SquareSequence();
double avg = average(squares, 100);
Java
복사
IntSequence is supertype
SquareSequence is subtype
단, interface class 는 객체를 만들 수 없다.
IntSequence squares = new IntSequence();
Java
복사
또한 형변환을 통하여 subtype에 superclass의 변수의 객체를 전달하는 것이 가능하다.
class DigitSequence implements IntSequence {
private int number;
public DigitSequence(int n) { number = n; }
public boolean hasNext() { return number != 0; }
public int next() {
int result = number % 10;
number /= 10;
return result;
}
public int rest() { return number; }
}
Java
복사
위와 같은 클래스가 있다고 하자(앞으로 많이 나올 것이다)
그렇다면 아래와 같이 형변환을 하여서 subtype class에 객체를 전달해 줄 수도 있다.
IntSequence squares = new DigitSequence(2345);
DigitSequence digits = (DigitSequence)squares;
System.out.println(digits.rest());
Java
복사
물론 subtype 끼리는 불가능하다.
IntSequence sequence = new SquareSequence();
DigitSequence digits = (DigitSequence)sequence;
System.out.println(digits.rest());
Java
복사
그렇다면 이게 과연 subtype class가 맞는지 확인하는 방법이 없을까? 이걸 위해서 자바에서는 instanceof 명령어를 제공하여 준다.
IntSequence sequence = new DigitSequence(2345);
if(sequence instanceof DigitSequence){
DigitSequence digits = (DigitSequence)sequence;
System.out.println(digits.rest());
}
Java
복사
그러면 우리가 기존에 사용하던 클래스에 기능만 추가하는 매우 평범한 방법은 없을까????
이게 바로 상속의 개념이다. 키워드는 extends로 아까전에는 implements를 사용한 곳에 extends 명령어를 사용하여 주면 된다.
interface Closeable{
void close();
}
interface Channel extends Closeable{
boolean isOpen();
}
Java
복사