본문 바로가기
  • 適者生存
WorkOut/정보처리기사

자바 | 메서드와 클래스, 인터페이스

by lcrvvxln 2024. 3. 23.

 

 

적자생존

8. 메서드

 

(1) 사용자 정의 함수 (메서드, User-Defined Function)


- 사용자가 직접 새로운 함수를 정의하여 사용하는 방법
- 사용자 정의 함수의 매개변수나 생성 변수는 사용자 정의 함수 종료 시, 없어짐

[1] 사용자 정의 함수 문법

// 자바 사용자 정의 함수 

public class Hoxypot {
   static char fn(int num){
      if(num%2==0)
        return 'Y';
      else
        return 'N';
   }
   
   public static void main(String[] args){
      char a=fn(5);
      System.out.print(a);
   }
}

// N
  • Hoxypot 클래스 선언
  • 문자형 변수를 반환하고 정수형 변수 num을 매개변수로 받는 사용자 정의 함수 fn 선언
  • 프로그램은 public static void main 부터 시작
  • 문자형 변수 a 선언 > 사용자 정의 함수 fn 호출 후,  전달인자로 5 전달한 결괏값을 a에 대입
  • 매개변수 num을 5로 하는 fn 함수 실행 > 5는 홀수이므로 2로 나눈 나머지가 1이기 때문에 else 문에 따라 'N'을 반환 > a='N'
  • num은 사용자 정의 함수의 매개변수이므로 사용자 정의함수 종료와 동시에 소멸
  • N 출력

 

(2) static 메서드

- 클래스가 메모리에 올라갈 때 자동적으로 생성되는 메서드
- **인스턴스** 생성 없이도 호출 가능

- 인스턴스 (Instance)

클래스로부터 만들어진 객체

 

// 자바 static 메서드

class Hoxypot{
   static void print(){
      System.out.println('static method');
   }
}

public class HoxypotMain{
   public static void main(String[] args){
      Hoxypot.print();
   }
}

// static method
  • Hoxypot class 생성 > 클래스 안 static 메서드 print 선언
  • public class HoxypotMain 생성
  • 프로그램은 public static void main부터 실행
  • 위에서 선언한 Hoxypot class의 print 메서드를 객체 생성하지 않고 Hoxypot.print 형태로 호출
  • print는 static 메서드이므로 인스턴스 생성 없이 호출 가능 > println에 의해 'static method' 출력
- 자바의 클래스 이름과 파일명

자바는 클래스 이름과 파일 이름이 같아야 함
**main 메서드**가 포함된 클래스가 기준

ex. 자바 static 메서드 예시에서는 main 메서드가 HoxypotMain class에 포함되어 있으므로 HoxypotMain.java 파일이 실행되는 것  




 

9. 클래스 (Class)


- 객체 지향 프로그래밍 (OOP : Object-Oriented Programming) 에서 **객체** 생성을 위해 **변수와 메서드**를 정의하는 틀

(1) 클래스 접근 제어자 (Access Modifier)


- 접근 제어자는 지정된 클래스, 변수, 메서드를 외부 (동일 패키지 혹은 외부 패키지)에서 접근할 수 있도록 권한을 설정하는 기능

[1] 클래스 접근 제어자 종류

  • public : 외부 모든 클래스에서 접근 가능한 접근 제어자
  • protected : 같은 패키지 내부 클래스, 하위 클래스 (상속받은 경우)에서 접근 가능, 자기 자신과 상속받은 하위 클래스 둘 다 접근 가능
  • default : 접근 제어자 명시하지 않은 경우, 같은 패키지 내부에 있는 클래스에서 접근 가능
  • private : 같은 클래스 내에서만 접근 가능
default는 자바에만 존재하는 접근제어자

 

[2] 클래스 정의

- 클래스의 변수는 변수 선언과 동일, 메서드는 사용자 정의 함수와 문법 동일
- 일반적으로 변수는 private 접근 제어자 사용, 외부 접근 불가하게 함
- 메서드는 외부에 공개할 것만 public, 그렇지 않으면 protected 나 private 접근 제어자 사용하여 **정보은닉**

- 정보 은닉(Information Hiding)

코드 내부 데이터와 메서드 숨기고 공개 인터페이스 통해서만 접근 가능하게 하는 코드 보안 기술
public class 클래스명{
   private 자료형 변수명;
   public 반환_자료형 메서드명(자료형 변수명, ...){
      명령어;
      return 반환값;
   }
}

 

(3) 클래스 변수 생성


- 클래스는 객체 생성을 위해 변수와 메서드를 정의하는 틀
- 실제 변수에 들어갈 인스턴스 **new** 키워드로 생성
- 변수를 이용해 클래스 메서드에 접근

클래스명 변수명 = new 클래스명(파라미터);
변수명.메서드명( );

 

(4) 클래스 this


- this는 **현재 객체** 가리키는 키워드
- 클래스 내부 변수와 메서드 가리킴

  • 클래스 내부 변수 접근 : this.변수;
  • 클래스 내부 메서드 접근 : this.메서드(매개변수);
  • 클래스 내부 생성자 호출 : this(매개변수);

 

// 자바 this
public class Hoxypot{
   private int a;
   public void setA(int a){
      this.a=a;
   }
   
   public int getA( ){
      return a;
   }
   
   public static void main(String[] args){
      Hoxypot ho = new Hoxypot();
      ho.setA(5);
      System.out.print(ho.getA());
   }
}

// 5
  • Hoxypot class 생성
  • 프로그램은 public static void main 부터 실행
  • ho  변수에 Hoxypot class 생성
  • Hoxypot class ho 변수에 setA 메서드 호출 > 매개변수로 5 전달
  • 클래스 Hoxypot의 public 메서드 setA는 전달인자로 정수 5를 전달 받음
  • this.a 를 통해 클래스 Hoxypot 내의 private a 변수에 접근하고 메서드 SetA가 전달받은 5를 대입
  • print 함수를 통해 ho.getA 함수 반환값 출력 > getA 메서드는 클래스 Hoxypot 내의 private 함수 a를 반환 > a=5 출력
- 프로그램에서 같은 이름의 변수가 2가지 이상일 경우

해당 구문과 가장 가까이 있는 변수를 지칭

ex. 자바 this 코드의 public setA 함수

public setA 함수는 전달받은 전달인자 a와 Hoxypot 클래스 내에 선언된 private 정수형 변수 a 모두 'a'로 지칭할 수 있게 된다

코드 'this.a=a;' 구문에서  
setA 함수가 전달받은 파라미터 a는 함수 내에 존재하고 있으므로 함수 밖의 클래스 private 변수 a보다 가까워서 'a'로 지칭할 수 있다
그 결과, 함수 밖의 클래스 private 변수 a를 지칭하기 위해 'this' 클래스를 사용

 

(6) 생성자 (Constructor)


- 생성자는 해당 클래스 객체가 생성될 때 자동으로 호출되는 특수한 메서드
- 일반적으로 클래스 멤버 변수를 초기화하거나 클래스 사용하는데 필요한 설정이 필요한 경우에 사용
- 생성자는 클래스 명과 동일한 메서드명을 가지며 반환값 없음
- 생성자 없을 경우, public 클래스명 ( ){ } 라는 아무 일도 하지 않는 생성자가 있는 것 처럼 동작

- 생성자 정의

public class 클래스명{
   public 클래스명 (매개변수) {
      명령어;
   }
}


- 생성자 호출

클래스명 클래스 변수 = new 클래스명(매개변수);

 

// 자바 생성자 메서드 

public class Hoxypot{
   public Hoxypot( ){
      System.out.println('A');
   }
   
   public Hoxypot(int a){
      System.out.println('B: '+a);
   }
   
   public void fn(){
      System.out.println('C');
   }
   
   public static void main(String[] args){
      Hoxypot h1= new Hoxypot();
      Hoxypot h2= new Hoxypot(5);
      h1.fn();
   }
}

// A
// B: 5
// C
  • Hoxypot class 선언
  • 프로그램은 public static void main부터 시작
  • Hoxypot h1= new Hoxypot( ); 은 매개변수가 없으므로 Hoxypot 생성자 호출 > 매개변수 없는 첫 번째 생성자 실행 > println 함수에 의해 A 출력
  • Hoxypot h2= new Hoxypot(5); 은 매개변수로 정수 5를 전달하므로 Hoxypot (int a) 생성자 호출 > println 함수에 의해 B: 5 출력
  • h1 객체에 대해 Hoxypot 클래스의 public fn 함수를 실행 > println 함수에 의해 C 출력




 

10. 클래스 상속 (Inheritance)


- 상속은 어떤 객체에 대해 그 객체의 변수와 메서드를 다른 객체가 물려받는 기능
- 자식 클래스는 무조건 부모 클래스의 생성자 실행 이후에 자식 클래스 생성자 실행

(1) 클래스 상속 문법

class 부모_클래스명{
}

class 자식_클래스명 extends 부모_클래스명{
}
- 부모 클래스
: 상위 클래스, 슈퍼 클래스

- 자식 클래스
: 하위 클래스, 서브 클래스
//자바 상속
class A{
   public void fnA( ){
      System.out.println('A');
   }
}

class B extends A{
   public void fnB(){
      System.out.println('B');
   }
}

public class Hoxypot{
   public static void main(String[] args){
      B b = new B();
      b.fnA();
      b.fnB();
   }
}

// A
// B
  • public class Hoxypot 선언
  • 프로그램은 public static void main 부터 실행
  • 위에서 선언한 class B 를 b 변수로 생성
  • b 변수를 이용해 fnA() 함수 호출 > B 클래스 내에는 fnA() 함수가 없지만 B 클래스는 a 클래스를 상속 받음 > A 클래스의 변수와 메서드를 사용할 수 있음
  • fnA()  함수를 통해 'A' 출력
  • b 변수를 이용해 fnB() 함수 호출 > fnB() 함수는 B 클래스 내에 존재하므로 fnB()함수 호출 > println 함수를 통해 'B' 출력

 

- 자바와 파이썬의 차이점

1. 자바
- 자식 클래스 생성 시, 부모 클래스 생성자 선 방문 후, 자식 클래스 생성자 방문

2. 파이썬
- 자식 클래스 생성 시, 자식 클래스 생성자만 방문

 

(2) 오버로딩(Overloading)


- 동일한 이름의 메서드를 매개변수만 다르게 하여 여러 개 정의할 수 있는 기능

  • 오버로딩 특징

1. 메서드 이름이 동일해야 함
2. 매개변수 개수가 달라야 함
3. 매개변수 개수가 같을 경우, 데이터 타입이 달라야 함
4. 반환형은 같든 다르든 상관 없다

생성자와 오버라이딩의 차이

- 생성자는 클래스명과 동일한 이름의 메서드
- 오버라이딩은 부모,자식 간 동일한 이름의 메서드
- 오버로딩은 메서드 간 동일 이름

**생성자는 오버라이딩 되지 않음**
// 자바 오버로딩
class A{
   public void fn( ){
      System.out.println('A');
   }
   public void fn(int i){
      System.out.println('i');
   }
   public void fn(double d){
      System.out.println(d);
   }
   public int fn(int a, int b){
      return a+b;
   }
}

public class Hoxypot{
   public static void main(String args[]){
      A a=new A();
      a.fn();
      a.fn(7);
      a.fn(10.0);
      System.out.println(a.fn(2,3));
   }
}

// A
// 7
// 10.0
// 5
  • Hoxypot class 생성
  • 프로그램은 public static void main 부터 실행
  • A 클래스를 a 변수에 생성 > A 클래스는 생성자 A()가 없으므로 생성 시 아무일도 발생 X
  • A 클래스 변수 a의 fn( ) 메서드 호출 > 전달인자가 없으므로 매개변수가 없는 첫 번째 fn 메서드인 것을 알 수 있음 > 'A' 출력
  • 변수 a가 정수 7을 전달인자로 하는 fn( ) 메서드 호출 > 전달인자가 1개이므로 매개변수 개수가 1개인 2,3 번째 메서드 중 하나인 것을 알 수 있음 > 2번째 메서드는 매개변수가 정수형, 3번째 메서드는 매개변수가 실수형인 double이므로 전달인자인 7에 따라 2번째 매개변수가 호출됨 > 매개변수인 i=7 출력
  • 변수 a가 실수 10.0을 전달인자로 하여 fn( ) 메서드 호출 > 이 역시 전달인자가 1개이므로 2,3 번째 메서드가 해당이지만 전달인자가 실수형이므로 3번째 메서드가 호출됨 > 매개변수인 d=10.0출력
  • println 함수를 이용해 변수 a가 fn ( ) 함수에 정수 2,3을 매개변수로 한 결괏값을 출력하도록 함 > 전달인자 개수가 2개이므로 매개변수 개수에 따라 정수형 매개변수 2개를 받는 마지막 fn( ) 함수가 호출됨
  • 마지막 fn 메서드의 결괏값음 매개변수로 받은 정수 a와 b를 더한 값이므로 a=2 + b=3 = 5 > 5 출력

 

(3) 오버라이딩 (Overriding)


- 오버라이딩은 하위 클래스에서 상위 클래스 메서드를 재정의하는 기능

  • 오버라이딩 특징

1. 오버라이드하고자 하는 메서드가 상위 클래스에 존재해야 함
2. 메서드 이름이 같아야 함
3. 메서드 매개변수 개수, 데이터 타입이 같아야 함
4. 메서드 반환형이 같아야 함

- 오버라이딩 구문

class 부모_클래스명{
   public 반환_자료형 메서드명(자료형 변수명){  }
}

class 자식_클래스명 extends 부모_클래스명{
   public 반환_자료형 메서드명(자료형 변수명){
      // 부모 클래스의 메서드명, 매개변수와 동일해야 함
   }
}

 

// 자바 오버라이딩
class A{
   public void fn(){
      System.out.println('A');
   }
}

class B extends A{ // 클래스 B가 클래스 A 상속받음
   public void fn( ){
      System.out.println('B');
   }
}

public class Hoxypot{
   public static void main(String args[]){
      A a = new B();
      a.fn();
   }
}

// B 
  • Hoxypot class 선언
  • 프로그램은 public static void main 부터 시작
  • B 클래스를 a 변수에 생성 > B 클래스 생성이므로 B 생성자 B( ) 와 상속된 A 클래스의 생성자 A( )가 호출되어야 하지만 둘 다 없기 때문에 아무 일도 발생 X
  • 변수 a는 B 클래스이므로 B 클래스의 fn 함수 호출 > B 클래스가 상속 받은 A 클래스에 'A'를 출력하는 fn() 함수가 있었으나 상속받은 B 클래스의 동일 메서드에 의해 'B'를 출력하는 메서드로  fn( ) 메서드가 재정의 됨 > B 출력

 

// 자바 생성자, 오버라이딩

class Parent{
   public Parent( ){
      System.out.print('A');
   }
   
   public Parent(int a){
      System.out.print('B');
   }
   
   public void fn( ){
      System.out.print('C');
   }
}

class Child extends Parent{
   public Child( ){
      System.out.print('D');
   }
   public Child(int a){
      super(a);
      System.out.print('E');
   }
}

public class Hoxypot{
   public static void main(String args[]){
      Parent a= new Parent();
      Parent b= new Parent(1);
      Parent c= new Child();
      Parent d = new Child(1);
      Child e = new Child();
      Child f = new Child(2);
      a.fn( );
      e.fn( );
   }
}

// ABADBEADBECF
  • Hoxypot class 선언
  • 프로그램은 public static void main부터 실행
  • Parent a 변수에 Parent 클래스 생성 > Parent 클래스 생성과 동시에 Parent( ) 생성자 호출 > 'A' 출력
  • Parent b 변수에 Parent 클래스 생성 > Parent 클래스 생성과 동시에 정수 1을 전달인자로 전달하므로 정수형 파라미터를 받는 Parent(int a) 생성자 호출 > B 출력
  • Parent c 변수에 Child 클래스 생성 > Child 클래스 생성과 동시에 Child( ) 생성자 호출 > 자바는 상속된 클래스 생성자 호출 전에 부모 클래스 생성자를 먼저 호출해야 하므로 매개변수 없는 Parent( ) 생성자 호출 > 'A' 출력 > 자식 클래스인 Child 클래스의 매개변수 없는 Child( ) 생성자 호출 > 'D' 출력
  • Parent d 변수에 Child 클래스 생성 > Child 클래스 생성과 동시에 정수 1을 전달인자로 전달하여 정수형 파라미터 받는 Child(int a) 생성자 호출
  • Child(int a) 생성자에 부모 클래스 생성자에 대한 명령어 super(a)가 있으므로 a=1 정수형 매개변수를 갖는 Parent(int a) 생성자 호출 > 'B' 출력
  • 다시 Child 생성자로 돌아와 'E' 출력
  • Child e 변수에 Child 클래스 생성 > Child 클래스 생성과 동시에 Child( ) 생성자 호출 > 부모 클래스의 생성자 Parent ( ) 호출 > 'A'  출력 > 다시 Child( ) 생성자로 돌아와 'D' 출력
  • CHild f 변수에 Child 클래스 생성 > Child 클래스 생성과 동시에 정수 2를 전달인자로 전달하여 정수형 파라미터 받는 Child(int a) 생성자 호출
  • 부모 클래스 생성자에 대한 명령어 super(a)에 따라 a=2 이므로 정수형 매개변수를 갖는 Parent(int a) 생성자 호출 > 'B' 출력
  • 다시 Child(int a) 생성자로 돌아와 'E' 출력
  • Parent 클래스가 생성된 Parent a 변수에 fn( ) 함수를 실행하므로 'C' 출력 (Parent 클래스가 인스턴스)
  • Child 클래스가 생성된 Child e 변수에 fn( ) 함수 실행 > 부모 클래스인 Parent의 fn( ) 함수와 동일한 fn( )메서드가 Child 클래스에서 재정의되었으므로 오버라이딩 되어 'F' 출력 (Child 클래스가 인스턴스)

 

- 자바 생성자, 오버라이딩 코드

1. new Parent( ); 코드에서 Parent만 보면 Parent 부모 클래스가 없기 때문에 Parent 생성자만 호출

2. new Child( ); 코드에서 Child 를 보면 부모 클래스가 Parent 이므로 Parent 생성자와 Child 생성자 모두 호출

 

- Parent x = new Child( );   VS  Child x = new Child( );

업캐스팅, 다운캐스팅 개념 필요

단순 결론 -> 동작 방식에 차이 없음 (???)

 

(4) 부모 클래스 접근


- 자바는 **super** 키워드를 이용하여 상위 클래스 변수나 메서드에 접근 가능

  • 부모 클래스 내부 변수 접근 : super.변수;
  • 부모 클래스 내부 메서드 접근 : super.메서드(매개변수);
  • 부모 클래스 내부 생성자 호출 : super(매개변수);

 

// 자바 상위 클래스 접근 

class A{
   public void fn( ){
      System.out.println('A');
   }
}

class B extends A{
   public void fn( ){
      super.fn( );
      System.out.println('B');
   }
}

public class Hoxypot{
   public static void main(String args[]){
      A a = new B();
      a.fn();
   }
}

// A
// B
  • Hoxypot class 선언
  • 프로그램은 public static void main 부터 실행
  • a 변수에 클래스 B 생성 > 클래스 B 생성과 동시에 B 생성자 B( )와 부모 클래스인 A의 생성자 A( )가 A() > B() 순서로 실행되어야 하지만 둘 다 없으므로 아무일도 일어나지 않음
  • a 변수가 fn( ) 함수 호출 > a 변수는 B 클래스이므로 B 클래스에 있는 fn( ) 메서드를 호출
  • B 클래스 fn ( ) 메서드는 부모 클래스에 대한 명령어 super.fn( ) 에 의해 A 클래스의 fn( ) 함수 호출 > println에 따라 'A' 출력
  • 다시 B 클래스의 fn( ) 함수로 돌아와서 println에 따라 'B' 출력

 




11. 추상 클래스 (Abstract Class)


- 추상 클래스는 **미구현 추상 메서드** 를 한 개 이상 가짐
- 자식 클래스에서 미구현 추상 메서드를 반드시 구현하도록 강제하는 기능


(1) 추상 클래스 구문

abstract class 추상_클래스명 {
   abstract 자료형 메서드명( ); // 메서드 내부는 정의하지 않음
}

class 자식_클래스명 extends 추상_클래스명{
   자료형 메서드명( ){
      명령어; // 메서드 상속 받아 미구현 추상 메서드 내부 정의
   }
}
- 메서드 내부를 정의하지 않는다

메서드 내부에 소스 코드를 이용하여 구현하지 않는다는 뜻

- 메서드 내부를 정의한다

메서드 내부를 소스 코드를 이용해서 구현한다는 뜻

 

// 자바 추상 클래스 
abstract class A {
   abstract void fn( ); // { } 기호를 이용하지 않고 메서드 내부를 정의하지 않음, 미구현 추상 메서드 
}

class B extends A {
   void fn( ){
      System.out.print('B');
   }
}

class C extends A{
   void fn( ){
      System.out.print('C');
   }
}

class Hoxypot {
   public static void main(String args[]){
      A b = new B( );
      A c = new C( );
      b.fn( );
      c.fn( );
   }
}

// BC
  • Hoxypot class 선언
  • 프로그램은 public static void main 부터 실행
  • b 변수에 B 클래스 생성 > B 클래스 생성과 동시에 B() 생성자와 부모 클래스인 A() 생성자가 호출되어야 하지만 둘 다 없기 때문에 아무일도 일어나지 않음
  • c 변수에 C 클래스 생성 > C 클래스 생성과 동시에 C() 생성자와 부모 클래스인 A() 생성자가 호출되어야 하지만 둘 다 없기 때문에 아무일도 일어나지 않음
  • 변수 b의 fn() 메서드 호출 > 변수 b는 B 클래스이므로 클래스 B의 fn( ) 함수 호출 > 부모 클래스인 A의 fn( ) 메서드는 내부가 정의되어 있지 않고 B 클래스에 의해 오버라이딩 되었으므로 B 클래스 fn 메서드가 실행됨 > 'B' 출력
  • 변수 c의 fn() 메서드 호출 > 변수 c는 C 클래스이므로 클래스 C의 fn() 함수 호출 > 부모 클래스인 A의 fn()메서드는 내부가 정의되어 있지 않은 미구현 추상 메서드이고 C 클래스에 의해 오버라이딩 되었으므로 C 클래스 fn() 메서드 실행 > 'C' 출력

 


 

12. 인터페이스


- 인터페이스는 자바의 다형성을 극대화하여 개발 코드 수정을 줄이고 프로그램 유지보수성을 높인다 ( 인터페이스는 일종의 추상 클래스)
- 오직 **추상 메서드와 상수**만 멤버로 가질 수 있고 그 외의 어떤 요소도 허용 X

- 인터페이스는 아무것도 구현된 것 없이 밑그림만 그려진 '기본 설계도'


(1) 인터페이스 구문

// 인터페이스 구문

interface 인터페이스_클래스명{
   자료형 메서드명( ); // 메서드 내부 정의 X
}

class 자식_클래스명 implements 인터페이스_클래스명{
   자료형 메서드명( ){
      // interface의 메서드를 상속받아 내부 정의
   }
}

 

// 자바 인터페이스 

interface A{
   void fn();
}

class B implements A{
   public void fn( ){
      System.out.print('B');
   }
}

class C implements B{
   public void fn(){
      System.out.print('C');
   }
}

class Hoxypot{
   public static void main(String args[]){
      A b = new B();
      A c = new C();
      b.fn();
      c.fn();
   }
}

// BC
  • Hoxypot class 선언
  • 프로그램은 public static void main 부터 실행
  • b 변수에 B 클래스 생성 > B 클래스 생성자와 부모 클래스인 A의 생성자 호출해야 하지만 둘 다 없으므로 호출 X
  • c 변수에 C 클래스 생성 > C 클래스 생성자와 부모 클래스인 A 생성자 호출해야 하나 둘 다 없으므로 호출 X
  • b 변수의 fn( ) 메서드 호출 > b 변수는 B 클래스이므로 B 클래스의 fn( ) 메서드 호출 > 부모 클래스인 인터페이스 A는 fn 메서드의 내부를 정의하지 않고 상속 받은 B 클래스에 의해 오버라이딩 되었으므로 B 클래스 fn( ) 함수에 의해 'B' 출력
  • c 변수의 fn() 메서드 호출 > c 변수는 C 클래스이므로 C 클래스의 fn() 메서드 호출 > 부모 클래스인 인터페이스 A는 fn 메서드 내부 정의 X ,상속 받은 c 클래스에 의해 오버라이딩 되었으므로 C 클래스 fn( ) 함수에 의해 'C' 출력
소스 코드 동작을 자세히 보면
abstract 클래스와 차이가 없음 (??)