Java,Spring

[자바 기초 문법] 객체 지향

뀨린 2021. 5. 13. 18:26

객체지향 기초

 

객체(object)의 개념

 

소프트웨어 객체는 현실 세계의 객체를 필드(상태)와 메서드(동작)로 모델링한 것이다. 

소프트웨어 객체는 상태를 필드로 정의하고, 동작을 메서드로 정의한다. 

필드는 객체 내부에 선언된 변수를 의미하고, 메서드는 객체 내부에 정의된 동작이다. 

 

클래스와 객체는 보통 붕어빵 틀과 붕어빵으로 이해하면 쉽다!

 

귀여운 물고기들로 이해하려하니까 용어가 친근하게 다가오는거같아요~~(아님말고!)

 

인스턴스 = 붕어빵의 실체라고 생각하면된다. 

 

객체 지향 프로그래밍의 특징

 

  • 캡슐화(정보 은닉): 관련된 필드와 메서드를 하나의 캡슐처럼 포장해 세부 내용을 외부에서 알 수 없도록 감추는 것이다. 

  • 상속: 자녀가 부모 재산을 상속받아 사용하듯 상위 객체를 상속받은 하위 객체가 상위 객체의 메서드와 필드를 사용하는 것이다. 
  • 상속은 개발된 객체를 재사용하는 방법 중 하나다.

  • 다형성: 대입되는 객체에 따라 메서드를 다르게 동작하도록 구현하는 기술로, 실행 도중 동일한 이름의 다양한 구현체 중에서 메서드를 선택 가능하다. 

 

  • 추상화(abstraction): 컴퓨터 시스템의 complexity level를 정의하고 설정함으로써, 사용자가 시스템의 복잡한 디테일들을 모르고도 시스템과 상호 작용이 가능케 해주는 기술이다. 현실 세계의 객체는 수많은 상태가 있고, 다양한 동작을 하지만 클래스에 모두 포함하기는 어렵기에 추상화하는 과정이 필요하다. 현실 세계의 불필요한 속성을 제거하고 중요한 정보만 클래스로 표현하는 일종의 모델링 기법이라고 볼 수 있다. 

클래스 선언과 객체 생성

 

public class Ball{

          //클래스 이름으로 소스 파일 이름과 동일해야한다!

 

}   👉ball.java

 

pacakage sec03;

class Phone{
    String model;
    int value;
    
    void print(){
       System.out.println(value + "만원 짜리" + model + "스마트폰");
    }
}

public class PhoneDemo{
   public static void main(String[] args) {
   
       Phone myPhone = new Phone();  //디폴트
       myPhone.model = "갤럭시 S8";
       myPhone.value = 100;
       myPhone.print();
       
       Phone yourPhone = new Phone();
       yourPhone.model = "66";
       yourPhone.value = 85;
       yourPhone.print();
   }
}

//output: 100만원 짜리 갤럭시 S8 스마트폰 
         // 85만원짜리 G6 스마트폰 

 

 

클래스 선언과 파일

 

보통 소스파일마다 하나의 클래스를 선언하지만, 2개 이상의 클래스를 하나의 파일로 선언이 가능하다. 하나의 파일에 클래스가 둘 이상 있다면, 하나만 public으로 선언할 수 있고, 해당 클래스 이름은 소스 파일 이름과 동일해야 한다!

 

객체 생성과 참조 변수

 

클래스 이름 변수; 👉 클래스는 참조 타입이므로 참조 변수 또는 참조 타입 변수라고 한다. 

 

변수 = new 클래스이름(); 👉생성자라고 한다. 

 

한 문장으로 변수 선언과 객체 생성

 

✔ new 클래스 이름();

 

기초 타입과 참조 타입

 

예제)

int ten = 10;

Ball myBall = new Ball(); //Ball은 클래스, myBall은 객체로 포인터처럼 메모리주소값을 가지고 있다. 

클래스의 구성요소와 멤버 접근

 

클래스의 구성요소

  •  멤버: 필드, 메서드
  •  생성자

필드와 지역 변수의 차이

 

  • 필드는 기본값이 있지만, 지역 변수는 기본값이 없어서 반드시 초기화해야 한다. 
  • 필드는 클래스 전체에서 사용할 수 있지만, 지역 변수는 선언된 블록 내부의 선언된 후에서만 사용이 가능하다. 
  • 필드와 달리 지역 변수는 final로만 지정이 가능하다. (지역변수는 static X)

필드와 메서드 접근

 

   객체참조변수.멤버

package sec04;

public class LocalVariableDemo{  //지역변수
    public static void main(String[] args){
    
    int a = 0;
    double b;
    
    //System.out.print(b);  //지역변수는 초기화 되어야만 사용 가능
    //System.out.print(a + c); //선언하지 않은 변수는 사용 불가
    
    int c = 0;
    //public double d = 0.0;  
    //static final double d = 0.0;   //지역변수는 static, public 선언 불가
      
    for (int e = 0l e < 10; e++) {
    //int a = 1;          //같은 블록 내에서 동일한 이름의 변수 사용 불가
        System.out.print(e);
    }    
  }
}

 

 

접근자와 설정자

 

왜 필요한가?

클래스 내부에 캡슐화된 멤버를 외부에서 사용할 필요가 있다. 

 

private으로 지정된 필드에 값을 반환하는 접근자와 값을 변경하는 설정자는 공개된 메서드다. 

접근자는 보통 get, 설정자는 set으로 시작하는 이름을 사용한다. 

필드 이름을 외부와 차단해서 독립시키기 때문에 필드 이름 변경이나 데이터 검증도 가능하다.

 

private double radius;

public double getRadius() { //접근자: getFieldName()
    return radius;        
}

public void setRadius(double r){  //설정자:setFieldName(parameter)
    radius = r;

}

 

생성자

 

의미와 선언

 

생성자의 역할: 객체를 생성하는 시점에서 필드를 다양하게 초기화한다.

생성자 사용

 

클래스 이름 변수 = new 클래스 이름(...);

 

package sec06;

public class CircleDemo {
    public static void main(String[] args){
        Circle myCircle = new Circle(10,0);
        //Circle yourCircle = new Circle();       
    }    
}

class Circle{

    private double radius;
    private String color;
    
    public Circle(double r, String c){
       radius = r;
       color = c;
    }
    
    public Circle(double r){
        radius = r;
        color = "파랑";
    }

    public Circle(String c){
       radius = 10.0;
       color = c;    
    }
    public Circle(){
        radius = 10.0;
        color = "빨강";
        }
}


////생성자 오버로딩 활용 예시

public class CircleDemo {
    public static void main(String[] args){
    Circle c1 = new Circle(10.0, "빨강");
    Circle c2 = new Circle(5.0);
    Circle c3 = new Circle("노랑");
    Circle c4 = new Circle();
    
    }

}
  • 생성자 이름은 클래스 이름과 같다.
  • 생성자 반환 타입은 없다. 
  • 생성자는 new 연산자와 함께 사용하며, 객체를 생성할 때 호출한다.
  • 생성자도 오버로딩 가능하다.

디폴트 생성자

 

모든 클래스는 최소 하나의 생성자가 있다.

만약 생성자를 선언하지 않으면 컴파일러가 자동으로 디폴트 생성자를 추가한다. 

 

class Circle {

   private double radius;
   public double getRadius() {...}
   public void setRadius(double radius) { ... }
   ...                                          //생성자를 하나도 선언하지 않았지만, 컴파일러가 디폴트 생성자인 Circle()을 자동으로 추가한다.
   

}

public class CircleDemo{

   public static void main(String[] args){
   
   Circle myCircle = new Circle(); //Circle 클래스에서 생성자를 선언하지 않았지만, Circle 생성자를 사용해 객체 사용이 가능하다. 
   
   }

}

 

생성자 오버로딩

 

생성자 또한 메서드처럼 오버로딩이 가능하다!

 

public class Demo_Cons{

   Demo_Cons(){ //생성자1, 매개변수 없음
      
   }
   
   Demo_Cons(int i){ //생성자2, 1 매개변수(int)
   
   }
   
   Demo_Cons(String s){ //생성자 3,매개변수(String)
      
   }

}

this와 this()

 

class Square{

    private double side; //멤버 필드이다. 
    
    public void setRadius(double s){  //멤버 필드처럼 정사각형 변을 의미하지만 변수 이름은 다름
    
    side = s;    
    }
}

class Square{

    private double side;
    
    public void setRadius(double side){  
    
    this.side = side; // 객체참조변수.멤버필드 = 매개변수
    
    }

}

 

정적 멤버

 

인스턴스 멤버와 정적 멤버

 

  • 자바는 static 키워드로 클래스의 필드를 공유할 수 있도록 지원한다.
  • 인스턴스 변수는 static 키워드로 지정되지 않아 공유되지 않은 필드로 인스턴스마다 자신의 필드를 생성한다. 
  • 정적 변수 혹은 클래스 변수는 static 키워드로 지정해 모든 인스턴스가 공유하는 필드이다. 
  • 인스턴스 변수는 객체별로 관리. 객체를 생성할 때 인스턴스 변수도 객체가 소멸될 때는 자동으로 소멸한다. 
  • 정적 변수는 클래스 로더가 클래스를 메서드 영역에 적재할 때 생성한다. 

정적 메서드 유의사항

 

  • 객체 관련 인스턴스 메서드 호출 불가능!
  • 객체 자신을 가리키는 this 키워드 사용 불가능!
  • 객체관련 인스턴스 변수 사용 불가능! 

 

정적 멤버의 활용

 

클래스이름.정적변수 이름 //정적 멤버는 일반적으로 클래스 이름과 연결해서 사용한다.

클래스이름.정적메서드이름()

 

상수는 변경되지 않는 변수기 때문에 final 키워드로 지정하지만, final로만 지정하면 객체마다 자신의 기억 공간을 가진다. 

상수는 값이 변경되지 않으므로, 객체마다 따로 기억 공간을 할당할 필요가 없다. 따라서 static final로 선언한다.

 

static final 데이터형 상수 = 초깃값;

 

 

 

참조: 쉽게 배우는 자바 프로그래밍 2판, 한빛아카데미, 우종정, 2020.

http://selab.gnu.ac.kr/oop/kor/ppts/gnu-lee-oop-kor-lec04-2-chap5.pdf