백엔드 수업 #06 클래스 - 08 메소드

sookyoung.k·2022년 11월 16일
2

정말... 쉽지 않은 클래스 공부. 생성자... '이샛길 왜 쓰는거임?' 에서 '그래 이렇게 쓰는거구나!' (현실 순응) 단계로 왔다. 근데 뭐... 세상만사 모든 것의 '왜'를 알 필욘 없지... ㅎㅎ. 그리고 있으면 편하니까 쓰는거겠지... 완전히 이해는 안 가지만 일단 계속 공부를 하고는 있다. 이제 슬슬 코딩 테스트도 해봐야 할 때가 온 것 같음. 암튼 메소드도 시작!


메소드 = 함수 (하나의 기능을 수행하는 코드)


메소드를 풀어 설명하자면 객체의 동작(기능)에 해당하는 중괄호 {} 블록을 말하는 것이다. 중괄호 블록의 이름이 바로 메소드 이름!

중괄호 블록 안에는 코드들이 있는데 메소드를 호출하게 되면 코드가 일괄 실행된다.

  • 필드를 읽고 수정하는 역할
  • 다른 객체를 생성, 다양한 기능을 수행하기도 함
  • 기능을 미리 구현해놓고 필요할 때마다 호출해서 사용

메소드 = 객체 간의 데이터 전달 수단으로 사용되는 것! (외부로부터 매개값을 받을 수도 있고, 실행 후 값을 리턴하기도 한다.)


메소드 선언

public int add (int num1, int num2) { // 선언부 
	... // 실행블록 
    return result;
}

메소드 선언은 이렇게 합니다.

하나씩 이름부터 살펴보자면,

  • 메소드의 구성: 선언부 (리턴타입, 메소드 이름, 매개변수선언) / 실행 블록

  • public int: 리턴 타입

  • add: 메소드 이름

  • int num1, int num2: 매개변수

  • return result: 반환값 (리턴 타입과 반환값의 타입은 꼭 일치해야 한다!)

리턴 타입 = 메소드가 실행 후 리턴하는 값의 타입

타입: 모든 기초자료형, 참조자료형, void

메소드마다 리턴값은 있을 수도 있고 없을 수도 있다. 왜냐하면 함수마다 리턴값이 필요한 경우도 있고 필요하지 않는 경우도 있기 때문임!

리턴값이 없는 메소드는 리턴 타입에 void가 와야 하고, 리턴값이 있는 메소드는 리턴값 타입이 와야 한다.

void powerOn() {...} // 전원을 켜기만 하면 되는 기능을 구현하는 거기 때문에 리턴값이 필요치 않음 
double divide(int x, int y) {...} // 나누는 기능을 구현해야 하기 떄문에 결과 리턴이 필요함 

리턴값의 유무에 따라 호출 방식이 달라진다.

powerOn();
double result = divide(10, 20); // 리턴 값을 받기 위해 변수를 double 타입으로 선언

변수에 저장할 내용이 없는 것 vs 저장할 변수가 있어야 하는것

메소드 실행이 중요할 경우에는 변수 선언 없이 메소드 호출 가능: divide(10, 20);

메소드 이름

  • 숫자로 시작하면 안됨.

  • $와 _를 제외한 특수 문자 사용 안됨

  • 관례적으로 메소드명은 소문자로 작성(단어 두 개 이상일 경우에는 카멜 타입으로 작성)

  • 기능 이름으로 지어주는 것이 좋다.

매개 변수 선언

메소드가 실행할 때 필요한 데이터를 외부로부터 받기 위해 사용된다!

마찬가지로 매개 변수도 필요한 경우가 있고 필요하지 않은 경우가 있음.

powerOn();
double result = divide(10, 20);

powerOn() 메소드는 전원만 켜면 되는 거니까 매개변수가 필요하지 않음
divide() 메소드는 나눗셈을 해야 하니까 두 수, 즉 매개 변수가 필요하다!

메소드를 선언할 때는 double divide(int x, int y) {...} 이런 방식으로 하면 된다.
그럼 반드시 두 개의 int 값을 줘야 함!

double result = divide(10, 20); 이렇게! 그러면 어떤 일이 일어나느냐...
10, 20이 해당 위치의 매개 변수인 x, y에 저장 → 매개 변수들을 이용하여 메소드 블록 실행!

메소드를 한 번 실행해 봅시다. 계산기의 네 가지 기능을 구현합니다.

public class Calculator {
	// 전원을 켜는 메소드 
    void powerOn() {
		System.out.println("전원을 켭니다.");
	}
    
    // int형으로 리턴값이 있는 메소드! 반드시 ★타입★을 써줘야 한다!!! 
    // 리턴타입, 매개변수 둘 다 타입이 있어야 함!!! 
    int plus(int x, int y) { 
		int result = x + y;
		return result;
	}
    
    // double형으로 리턴값이 있는 메소드! 
    double divide(int x, int y) { // double 타입과 int 타입은 result가 필요함!! 
		double result = (double)x / (double)y;
		return result;
	}
    
    // 전원을 끄는 메소드 
    void powerOff() {
		System.out.println("전원을 끕니다.");
	}
}

그렇다면! 메소드를 호출하여 실행을 시키려면?! 정답: 객체를 생성한다★ 이젠 좀 ... 아시겟나요?

public class CalculatorExample {
	public static void main(String[] args) { 
    	Calculator myCalc = new Calculator(); // 객체를 생성하고! myCalc라는 참조 변수 선언! 
		myCalc.powerOn(); // myCalc 변수에 도트(.)와 메소드 이름 형태로 호출하면 블록 실행! 
		
		int result1 = myCalc.plus(5, 6); // 받아올 변수 = 5, 6을 x, y에...!
		System.out.println(result1); // 결과: 11 
		
		int x = 10, y = 4; // 자동형변환 일어난다! (타입 주의해야 함) 
		double result2 = myCalc.divide(x, y); 
		System.out.println(result2); // 결과: 2.5
		
		myCalc.powerOff();
    }
}

매개 변수의 수를 모를 경우

맹세코 이건 수업 때 안 한 것 같은데... 아직 안 한 걸수도 있음. 배우면 쓸래.

리턴(return)문

리턴값이 있는 메소드

메소드 선언에 리턴 타입이 있는 메소드는 반드시 리턴(return)문을 사용해서 리턴값을 지정해야 한다!

return 리턴값;

"return"

  1. 결과를 반환한다
  2. 메소드 종료 (그래서 return문 이후의 실행문은 실행되지 않음. 에러남!)

리턴값이 없는 메소드(void)

"void"

  1. return을 생략해도 된다.
  2. 결과값이 없다.

생략하지 않을 경우! return; 이렇게 리턴문을 사용하면 메소드 실행이 종료된다.

메소드 호출

클래스 내부에서 호출할 경우에는 단순한 메소드 이름으로 호출하면 되지만,
클래스 외부에서 호출할 경우에는 우선 클래스로부터 객체를 생성한 뒤, 참조 변수를 이용하여 메소드를 호출해야 한다.

객체 내부에서 호출

public class Calculator {
	int plus(int x, int y) {
    	int result = x + y; // 4. 호출된 plus() 메소드 실행 후 리턴값을 준다. (17)
        return result; 
    }
    
    double avg(int x, int y){
    	double sum = plus(x, y); // 3. 실행된 avg() 메소드에서 plus() 메소드 호출
        // 5. plus() 메소드에서 받은 리턴값을 sum 변수에 저장 (plus(x, y)의 값이 sum 변수에 저장! = 연산자의 의미를 생각해보면 이해가 쉬움. 우측 값을 좌측에 저장)
        double result = sum / 2; // 6. 저장 후 실행됨! (17 / 2)
        return result; 
    }
    
    void execute() {
    	double result = avg(7, 10); // 2. 호출된 execute() 메소드에서 avg() 메소드 실행 
        // 7. 실행 결과를 execute() 메소드로 리턴값을 준다. (8.5)
        println("실행결과: " + result); // 8. println()을 호출한 후 리턴값을 매개값으로 넘겨줌
    }
    
    void println(String message) { 
    	System.out.println(message) // 9. 매개값으로 받은 문자열을 여기서 콘솔로 출력! 
    }
    
}

public class CalculatorExample {
	public static void main(String[] args) {
    	Calculator myCalc = new Calculator(); // 1. execute() 메소드 호출 
        myCalc.execute();
    }
}

[출력 결과] 실행결과: 8.5

객체 외부에서 호출

public class Car2 {
	// 인스턴스 필드	
	int speed;
    
    // 생성자
	
	// 인스턴스 메소드
    int getSpeed() {
    	return speed; // 6. 리턴값 받아서 
    }
    
	void run() { // 3. run() 메소드 실행 
		for(int i = 10; i <=50; i+=10) { // 3_1. 초기값 10에서 10씩 50까지 커진다. 
        	speed = i;
            System.out.println("달립니다. (시속:" + speed + "km/h)") // 4. if문이 끝날 때까지 출력 
        }
	}
}

public class CarExample {
	public static void main(String[] args) {
    	Car myCar = new Car(); // 1. 객체 생성! 메소드는 객체에 소속된 멤버이기 때문에 객체가 존재해야 메소드도 존재한다. 
        myCar.run(); // 2. 도트(.)연산자를 사용해서 run() 메소드 호출 
        int speed = myCar.getSpeed(); // 5. getSpeed() 메소드 호출 
        System.out.println("현재 속도: " + speed + "km/h"); // 7. 출력 
    } 	
}

[출력 결과]
달립니다.(시속:10km/h)
달립니다.(시속:20km/h)
달립니다.(시속:30km/h)
달립니다.(시속:40km/h)
달립니다.(시속:50km/h)
현재 속도: 50km/h

메소드 오버로딩(overloading)

클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것!

[조건] ★ 매개 변수의 타입, 개수, 순서 중 하나가 달라야 한다.

메소드 오버로딩을 하는 이유가 뭘까요!

  • 코드를 살짝 다르게 해서 다른 결과값을 줄 수 있기 때문이다! 이름은 같지만 디테일에서 차이를 줄 수 있음.
  • 매개값을 다양하게 받아서 처리할 수 있게 해준다!
public class Calculator {
	// 정사각형의 넓이 
	double areaRectangle(double width) { 
		return width * width; // 3. 메소드 실행 후 리턴 값을  result1에 저장 
	}

	// 직사각형의 넓이 
	double areaRectangle(double width, double height) { // 6. 이 메소드가 실행됨. 이하 동문. 
		return width * height;
	}
}

public class CalculatorEX {
	public static void main(String[] args) {
    	Calculator myCalc = new Calculator(); // 1. 객체 생성
		
		// 정사각형의 넓이 구하기 
		double result1 = myCalc.areaRectangle(10); // 2. 매개값을 10 하나 주고 areaRectangle() 메소드 호출 
		System.out.println(result1); // 4. 리턴값 실행 (100.0) 
		
        // 직사각형의 넓이 구하기 
		double result2 = myCalc.areaRectangle(10, 20); // 5. 매개값을 두 개 받음! 뭐가 호출될 지는 알겠죠.  
		System.out.println(result2); // 7. 실행 200.0
    }
}

=> Calcultor 클래스에 areaRectangle() 메소드를 오버로딩

  1. 매개값이 한 개: 정사각형의 넓이
  2. 매개값이 두 개: 직사각형의 넓이를 계산해서 리턴함

어떤 메소드가 호출될 지는 매개값의 수에 따라 달라지는 것이다.


알 것 같으면서도 여전히 용어가 헷갈려서 이해하는데 어려움을 겪는다. 그래도 조금은 코드가 어떤 방식으로 실행되고 읽히는지는 알 것 같은데... 이러고 또 모름. ㅠ. 메소드는 여기까지 정리!

profile
영차영차 😎

2개의 댓글

comment-user-thumbnail
2022년 11월 21일

열공하고있군요

1개의 답글