본문 바로가기

프로그래밍/Java

클래스의 기본, 변수와 메소드

절차 지향 vs 객체 지향

📌 절차 지향(Procedual Programming)

: 순차적 처리가 중시, 프로그램 전체가 유기적으로 연결되도록 만드는 프로그램 기법

 

장점: 컴퓨터 처리구조와 유사해 실행속도 빠름

단점: 유지보수가 어렵고, 실행 순서가 정해져 있어 코드 순서가 바뀌면 동일한 결과를 보장하기 어려움

 

📌 객체 지향(Object Oriented Programming)

: 실제 세계를 모델링하여 소프트웨어를 개발하는 방법, 데이터와 절차를 하나의 덩어리로 묶어서 생각 ex) 조립식 컴퓨터 

 

✅ 장점

1. 코드 재활용성 高

2. 절차지향보다 코딩 간편

3. 디버깅 쉬움

 

✅ 단점

1. 절차지향보다 처리속도 느림

2. 설계에 많은 시간 소요

 

✅ 특징

1. 캡슐화

- 관련 데이터와 알고리즘(코드)이 한 묶음으로 정리된 것으로 오류의 범위를 최소화 

- 데이터를 감추고 외부 세계와의 상호작용은 메소드를 통하는 방법

2. 상속: 이미 작성된 클래스를 이어 받아 새로운 클래스를 생성하는 기법(기존 코드 재활용)

3. 다형성: 하나의 이름(방법)으로 많은 상황에 대처하는 기법, 동일 작업 함수들에 똑같은 이름을 부여해 코드 간단해짐

 

 


 

변수 종류 

📌 전역 변수(Global Variable): class 영역에 선언된 변수 (=멤버 변수, 필드)

 

 타입 앞에 'static' 유무에 따라 클래스 변수(Class Variance), 인스턴스 변수(Instance Variable)로 나뉨

✅ 클래스 변수: 클래스가 선언이 된 순간부터 프로그램이 끝날 때까지 메모리에서 지워지지

                          변수가 필요하지 않을 때도 메모리를 잡아먹기 때문에 비효율적일 수 있음

 

📌 지역 변수(Local Variable): method 영역에 선언된 변수, method 내에서만 동작, method가 끝나면 소멸

 

✅ 하나의 함수 및 method가 단위가 되어 해당 함수가 실행될 때 

 

변수 종류 선언 위치 메모리 영역
전역 변수 클래스 변수 클래스 영역 메서드 (Method)
인스턴스 변수 힙(Heap)
지역 변수 메서드 영역 스택(Stack)

 

📌 매개 변수(Parameter): 생성자, 메서드의 소괄호 안에 적은 변수, 어떤 값이 들어올지 값의 형태를 정해줌

 

 

 


 

 

Class

📌 자바의 가장 작은 단위

 

 

📌 객체를 만들어내기 위한 설계도, 틀

 

객체(object): 소프트웨어 세계에 구현할 대상

인스턴스(instance): 설계도를 바탕으로 소프트웨어 세계에 구현된 구체적 실체

 

 

<example>

🍩 Class: 도넛 틀

🍩 Object: 도넛

🍩 Instance: 오리지널 도넛, 초코 도넛, 크림 도넛

 

*클래스*
public class Frame {
  ...
}

* 객체와 인스턴스 *
public class Main {
  public static void main(String[] args) {
    Frame doughnut; // '객체'

    // '인스턴스화'
    choco doughnut = new Frame(); // choco은 Frame 클래스의 '인스턴스'(객체를 메모리에 할당)
    original doughnut = new Frame(); // original은 Frame 클래스의 '인스턴스'(객체를 메모리에 할당)
  }
}

 

📌 class의 구성요소

1. 상태(state): 변수, class 안 method 밖에 정의

2. 행동(behavior): 메소드

 

public class Person {	
	String name;
    	String gender;
   	int age;
    
	Person(){}; 
}

 

public: 접근 제어자(acess modifier) 

class Person: Person 이라는 이름의 class 선언

String name, String gender, int age: 상태(state)

Person(){}: 생성자(contructor)

 

☑️ 접근 제어자: 클래스, 메소드, 인스턴스, 클래스 변수 선언 시 사용

1. public: 누구나 접근할 수 있도록 할 때 사용

2. protected: 같은 패키지 내에 있거나 상속받은 경우에만 접근 가능

3. package-private: 같은 패키지 내에 있을 때만 접근 가능

4. private: 해당 클래스 내에서만 접근 가능

 

☑️ 생성자: 객체를 생성하기 위한 도구

- class는 껍데기라 그 자체로 일을 할 수 없고, 객체를 생성해야 일을 시킬 수 있음

ex) stella라는 객체를 생성해야 stella의 자기소개를 할 수 있음

 

class name(type 변수명, type 변수명, ...){인스턴스 변수 초기화 내용}

 

- Person() 처럼 매개 변수가 없는 생성자를 "기본 생성자"라고 하고, 굳이 만들지 않아도 클래스 파일 안에 자동으로 만들어짐

- Person(String name, String gender, int age) 처럼 매개변수 설정 가능

 

public class Person {
	
	String name;
	String gender;
	int age;
		
	Person(String name, String gender, int age){	
		this.name = name;
		this.gender = gender;
		this.age = age;
	}
}

 

☑️ this: 객체에 대한 참조 값, 전역 변수매개 변수를 구분하기 위해서 사용

 

public class main{
	public static void main(String[] args){
    	Person stella;
        
        Person stella = new Person("stella", "female", 17);
    }
}

 

 


 

 

Method

📌 어떤 값을 주고 결과를 넘겨주는 것

 

📌 method의 구성

1. 제어자(modifier): 메소드의 특성을 정하는 부분

2. 리턴 타입(return type): 메소드가 끝냈을 때 돌려주는 타입

3. 메소드 이름(method name): 소괄호 앞에 있는 메소드의 이름

4. 매개 변수 목록(parameter list): 소괄호 안에 있는 매개 변수의 목록

5. 예외 목록(exception list): 메소드의 소괄호가 끝나는 부분과 중괄호가 시작하는 부분 사이에 선언

6. 메소드 내용(method body): 중괄호 안에 있는 내용

** method 선언 시 반드시 있어야 하는 것: retrun type, name, body **

 

 

public void introduce() {
 	System.out.println("저의 이름은 " + name + "이고, 성별은 " + gender + 
 	", 나이는 " + age + "살 입니다.");
			
}

 

public : 제어자

void: 리턴 타입

introduce: 메소드 이름

✅ System.out.println("저의 이름은 " + name + "이고, 성별은 " + gender + ", 나이는 " + age + "살 입니다.");

       : 메소드 내용

 

 ☑️ void: 메소드가 아무것도 돌려주지 않는 경우

 

 

 


 

 

상속(Inheritance)

📌 부모 클래스의 변수메소드를 물려받음

 

📌 접근 제어자가 public or protected로 선언되어 있는 변수와 메소드만 가능!

 

📌 접근 제어자가  없거나 private으로 선언된 것들은 자식 클래스에서 사용 ❌

 

📌 상속 선언

 

class 자식 클래스명 extends 부모 클래스명

 

📌 오버라이딩(overriding): 부모 클래스에서 정의된 메소드를 자식 클래스에서 같은 시그니쳐(조건)를 갖는 메소드로 재정의 하는 것

 

✅ 시그니쳐(조건)

1. 접근 제어자: 확장 가능

2. 리턴 타입

3. 메소드 이름

4. 매개 변수 타입 및 개수

 

public class Parent {
	
	public void check() {
		System.out.println("부모 메소드");
	}
	
	public void sum(int x, int y) {
		int sum = 0;
		for(int i = x; i <=y; i++) {
			sum += i;
		}
		System.out.println("합계 : " + sum);
	}	
}

public class Child extends Parent{
	
	public void check() { // 메소드 오버라이딩
		System.out.println("자식 메소드");
	}
	
	public void sum(int x, int y) { // 메소드 오버라이딩
		int sum = 0, odd = 0, even = 0;
		for(int i = x; x <= y; i++) {
			sum += i;
			if(i%2 ==0) {
				even += i;
			}else {
				odd += i;
			}
		}
		System.out.println("합계 : " + sum );
		System.out.println("짝수 합 : " + even + " / 홀수 합 : " + odd + ")");
        // super.sum(x, y) // 부모 메소드 호출 
	}
}

public class Overriding {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Child child = new Child();
		child.check();
		child.sum(0,  10);
	}
}

 

오버라이딩 결과

- 부모 method는 은닉되고 자식 클래스에서 재정의 된 메소드만 기본적으로 호출

- 필요 시 super. 으로 부모 method 호출

 

📌 오버로딩(overloading): 서로 다른 시그니처(매개변수의 개수, 타입)를 갖는 여러 메소드를 같은 이름으로 정의하는 것

⚠️ 리턴 값만 다른 오버로딩은 작성 ❌

 

장점

1. 메소드에 사용되는 이름 절약

2. 매개변수의 개수, 타입에 상관 없이 메소드 호출 가능

 

❗️객체 지향의 특징 중 '다형성'을 구현하는 방법 중 하나

 

public class Overloading {
	
    // test라는 메소드의 매개변수를 각가 다른 개수, 타입으로 설정
	public void test() {
		System.out.println("매개변수 없음");
	}
	
	public void test(int a, int b) {
		System.out.println("매개변수 " + a + "와 " + b);
	}
	
	public void test(double c) {
		System.out.println("매개변수 "+ c);
	}
}


...


public class Overloading_ex {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Overloading load = new Overloading();
		
		load.test();
		
		load.test(123, 456);
		
		load.test(3.141592);	
	}
}

 

오버로딩 결과

매개변수 없음

매개변수 123와 456

매개변수 3.141592

 

구 분 오버라이딩(overriding) 오버로딩(overloading)
메소드 이름 동일 동일
매개변수 타입, 개수 동일 다름
리턴 값 동일 상관 없음