다잘하고싶어

자바 클래스와 객체(1) 본문

이론학습/JAVA

자바 클래스와 객체(1)

챙영잉 2023. 1. 18. 11:25
목차
객체지향프로그래밍
   객체를 어떻게 만들까?
   객체지향프로그래밍의 특징
      A PIE(4가지)
      객체지향 프로그래밍의 장점
   클래스
      클래스의 구성
      클래스 선언형식
      패키지
      코드
   변수
      코드
   메서드
      메서드 선언 형식
      코드
      메서드의 종료 시점?
      메서드 오버로딩
   생성자 메서드
      디폴트 생성자(기본생성자)
      파라미터가 있는 생성자

 

객체지향 프로그래밍

정의

  • 프로그래밍을 할 때 객체 단위로 나눠서 하는 것 → 객체 간의 상호작용 이용

객체

  • 사물과 같이 유형적인 것과 개념이나 논리와 같은 무형적인 것들

객체모델링

  • 현실세계의 객체를 SW 객체로 설계하는 것
  • ex. 학사관리 시스템
    • 학생
      • 전공
      • 학번
    • 과목
      • 담당교수
      • 커리큘럼
    • 교수님
    • 교직원
객체지향프로그래밍의 등장배경

그 이전에 절차적 프로그래밍이 존재
→ 한계
(1) 유지보수 어려움
(2) 정해진 순서가 있어 순서를 바꾸면 결과를 보장할 수 없음
(3) 코드가 길어지면 가독성이 떨어짐
(4) 협업이 어려움 ( 대형 프로젝트에 부적합)

⇒ 한계를 극복하기 위해 “객체지향 프로그래밍” 등장

객체를 어떻게 만들까?

→ (1) 가장 먼저 설계도를 만들어야 한다 ⇒ 클래스

  • 클래스 Class = 객체를 만드는 설계도

→ (2) 설계도를 바탕으로 객체를 만든다 ⇒ 인스턴스

  • 인스턴스 Instance = 클래스를 통해서 생성된 객체
  • 객체는 데이터와 알고리즘을 가지고 있다.
    • 객체의 데이터는 인스턴스 별로 고유한 값이다.
    • 알고리즘은 없을 수도 있다.

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

A PIE

추상화 Abstraction

  • ex. 학사관리시스템을 만들 때, 학생이라는 클래스, 학생의 사소한 정보(강아지 유무) 까지는 필요없음
  • ⇒ 필요한 속성만을 추출해내는 것

다형성 Polymorphism

  • 하나의 객체를 여러 관점에서 바라볼 수 있다
  • ex. 사람 → 동물, 포유류, 객체, 생명체..

상속 Inheritance

  • 객체를 만들 때 필요한 설계도가 존재. 이전에 가지고 있는 설계도를 활용해서 새로운 설계도를 만드는 것

캡슐화 Encapsulation

  • 객체를 하나의 캡슐로 본다
  • 정보은닉 → 사용자가 객체를 사용할 때 그 객체의 모든 데이터와 알고리즘을 알 필요는 없음.
  • ex. 비행기를 탈 때 그 모든 구조와 설계를 알 필요는 없다.

객체지향 프로그래밍의 장점

  • 모듈화된 프로그래밍
    • 모듈? 기능별로 나누어져 있는 프로그램
    • 유지보수와 재사용이 용이하다
    • 협업에 유리
  • 재사용성이 높다

클래스

  • 관련있는 변수와 함수를 묶어서 만든 사용자정의 “자료형”
  • 모든 객체들의 생산처
  • 클래스 = 객체를 생성하는 틀(설계도)
  • 각 객체들이 어떤 특징(속성(데이터)과 동작(모듈))을 가지고 있을 지 결정

클래스의 구성

  • 속성 - 필드
  • 동작 - 메서드
  • 생성자 ⇒ 객체를 생성할 때 호출하는 것
  • 중첩클래스

클래스 선언 형식

  • [접근제한자] public , default ...
  • [활용제한자 ] final, abstract ...
public class Person {
	String name;
	int age;

	public void eat(){
  }

	public Person(){
  }
}
  • 클래스명 변수명 = new 클래스명()
  • 변수명.필드명
  • 변수명.메서드명()

패키지

  • 클래스가 모여있는 폴더
  • 모든 클래스는 특정 패키지에 속해있음

코드

public class Person {
	//필드
	String name;
	int age;
	
	//생성자
	//클래스명과 같다
	//반환형을 지정x
	public Person() {
		
	}
	
	//메서드
	public void eat() {
		System.out.println(name + "이 식사를 합니다.");
	}

}
package test01;

public class PersonTest {
	public static void main(String[] args) {
		Person p1 = new Person(); //객체의 생성: new 키워드 + 생성자 호출
		p1.name = "윤그린";
		p1.age = 30;
		p1.eat();
		
		Person p2 = new Person();
		p2.name = "홍홍홍";
		p2.age = 22;
		p2.eat();
	}
}

변수

클래스변수

  • 클래스 영역 선언( static 키워드)
  • 생성시기 : 클래스가 메모리에 올라갔을 때
  • 모든 인스턴스가 공유함

인스턴스변수

  • 클래스 영역 선언
  • 생성시기 : 인스턴스가 생성되었을 때( new)
  • 인스턴스 별로 생성됨

지역변수

  • 클래스 영역 이외( 메서드, 생성자.. 등)
  • 생성시기 : 선언되었을 때

코드

package test02;

public class Person {
	//static 키워드 → 클래스변수
	static String species = "호모 사피엔스 사피엔스";
	
	//인스턴스 변수
	String name;
	int age;
	
	//생성자를 만들지 않음
	
	public void eat() {
		//지역변수 local variable
		String dish = "짜장면";
		
	}
}
  • static 키워드 → 클래스변수 = 이 클래스로 생성되는 모든 인스턴스가 공유
  • static 키워드가 없다면? -> 인스턴스 변수
package test02;

public class PersonTest {
	public static void main(String[] args) {
		//생성자를 선언하지 않았는데 어떻게 사용가능?
		//생성자를 선언하지 않으면 컴파일러가 자동으로 기본생성자를 만들어준다.
		Person p1 = new Person();
		Person p2 = new Person();
		Person p3 = new Person();
		
		System.out.println(Person.species); //클래스변수 이므로 클래스명. 으로 접근 가능
		System.out.println(p1.species);
		System.out.println(p2.species);
		System.out.println(p3.species);
		

	}

}
  • 생성자를 따로 생성하지 않으면 컴파일러가 자동으로 기본 생성자를 생성해준다.

메서드

  • 객체가 할 수 있는 행동 정의
  • 어떤 작업을 수행하는 명령문의 집합에 이름을 붙여놓은 것.

메서드 선언 형식

public static void main(String [] args) {

}

코드

package test03;

public class Person {
		String name;
		int age;
		
		//메서드
		public int add(int a, int b) {
			return a + b;
		}
		
		public void eat() {
			String dish = "짜장면";
		}

}
package test03;

public class PersonTest {
	public static void main(String[] args) {
		Person p1 = new Person();
		int sum = p1.add(4, 5);
		
		System.out.println(sum);
	}

}

메서드의 종료시점?

  • 블록의 끝을 만날 때
  • 리턴문을 만날 때

(+) 반환형이 없는 void 에서도 리턴문을 사용할 수 있다.

  • 중간에 return 문을 만나면 메서드는 종료된다.
			// void 형에서 return 사용하기
		public void study(String subject) {
			double probability = Math.random();
			System.out.println(subject + "를 공부합니다.");
			System.out.println("알고리즘 스터디를 합니다");
			
			if(probability < 0.9999) {
				return;
			}
			
			System.out.println("게임을 합니다.");
			System.out.println("롤 영상을 시청합니다.");
		}
public class PersonTest {
	public static void main(String[] args) {
		Person p1 = new Person();
		int sum = p1.add(4, 5);
		
		System.out.println(sum);
		p1.study("자바");
	}

}

메서드 오버로딩

  • 이름이 같고 매개변수가 다른 메소드를 여러개 정의하는 것
  • 중복코드에 대한 효율적 관리 가능
  • 파라미터의 개수 또는 순서, 타입이 달라야 한다( 이름만 다른것은 안됨! )
  • 반환형만 다른 것은 의미 없음
public int add(int a, int b) {
			return a + b;
		}
		
public double add ( double a, double b) {
			return a+b;
		}
public class PersonTest {
	public static void main(String[] args) {
		Person p1 = new Person();
		int sum = p1.add(4, 5);
		System.out.println(sum);
		
		double sum2 = p1.add(2.7, 34.5);
		System.out.println(sum2);
	}
}

장점?

  • 다양한 자료형의 메서드를 만들 때 이름을 똑같이 할 수 있음 → 생산성 증가
    • 불가능 하다면 addInt(), addDouble() 이런식으로 다 다르게 설정해야함.
		public void eat() { 
			System.out.println("식사를 합니다");
		}
		public void eat(String dish) { 
			System.out.println(dish + "를 먹습니다.");
		}
		public void eat(String dish, int times) { 
			System.out.println(dish + "를" + times + "번 먹습니다.");
		}

매개변수의 순서가 다르면 메서드오버로딩을 사용할 수 있을까?
⇒ 가능!

		public void eat(String dish, int times) { 
			System.out.println(dish + "를" + times + "번 먹습니다.");
		}
		public void eat( int times, String dish) { 
			System.out.println(dish + "를" + times + "번 먹습니다.");
		}

생성자 메서드

  • new 키워드와 함께 호출하여 객체 생성
  • 클래스명과 동일
  • 결과형 리턴값을 갖지 않음 (void 도 쓰지 않음) = 반환타입 없다
  • 객체가 생성될 때 반드시 하나의 생성자 호출
  • 매개변수의 개수가 다르거나, 자료형이 다른 여러개의 생성자가 있을 수 있음(생성자 오버로딩)
  • 생성자의 첫번째 라인으로 this() 생성자를 사용하여 또 다른 생성자를 하나 호출 가능

디폴트 생성자(기본생성자)

  • 클래스 내게 생성자를 따로 정의하지 않으면 JVM이 자동으로 제공함.
  • 형태 : 매개변수가 없는 형태, 클래스명(){}

파라미터가 있는 생성자

  • 생성자의 목적이 필드 초기화
  • 생성자 호출 시 값을 넘겨주어야 한다
  • 해당 생성자를 작성하면 JVM 에서 기본 생성자를 추가하지 않음.
public class Person {
		String name;
		int age;

		public Person(String name, int age) {
			//매개변수로 멤버변수를 초기화
			//어떻게 구분할까?
			//this 키워드 사용 : 인스턴스의 멤버에 접근
			this.name = name;
			this.age = age;
			
		}
}
  • 클래스의 멤버변수와 인스턴스의 멤버변수를 어떻게 구분할까?

         ⇒ this 키워드 사용

this

  • this 키워드 사용하여 인스턴스의 멤버에 접근 가능.
  • 참조변수로써 객체 자신을 가리킴
  • 지역변수(매개변수)와 필드의 이름이 동일할 경우 필드임을 식별할 수 있게 함
  • 객체에 대한 참조이므로 static 영역에서는 this를 사용할 수 없음.
    • static 영역은 클래스 단위
public class Person {
		String name;
		int age;
		
		public Person() {
			this("라라라",55);
		}
		
		//파라미터가 있는 생성자
		public Person(String name, int age) { 
			this.name = name;
			this.age = age;
			
		}
}
public class PersonTest {
	public static void main(String[] args) {
		Person p1 = new Person("가가가", 28);
		Person p2 = new Person("나나나", 25);
		Person p3 = new Person("다다다", 32);

		System.out.println(p1.name);
		System.out.println(p2.name);
		System.out.println(p3.name);
		
		
		Person p4 = new Person();
		System.out.println(p4.name);

	}
}

결과:

this 의 활용

  • this.멤버변수
  • this( [ 인자값]) : 생성자 호출
  • this 생성자 호출 시 제한사항
    • 생성자 내에서만 호출이 가능함
    • 생성자 내에서 첫번째 구문에 위치해야한다

'이론학습 > JAVA' 카테고리의 다른 글

클래스 다이어그램 아이콘  (0) 2023.01.21
자바 : JVM 메모리 구조 이해하기  (0) 2023.01.19
자바 클래스와 객체(2)  (0) 2023.01.19
자바 배열  (0) 2023.01.17
자바기초  (0) 2023.01.16