SturdyCobble's Study Note

[프로그래밍] 5.1 클래스(1) - 클래스와 접근지정자 본문

휴지통/['19.06-'20.07]프로그래밍101

[프로그래밍] 5.1 클래스(1) - 클래스와 접근지정자

StudyingCobble 2019. 8. 31. 22:36

NOTICE : 독학인 만큼, 잘못된 내용이 있을 수 있습니다. 내용 지적은 언제나 환영합니다.

더 이상 이 블로그에는 글을 올리지는 않을 예정입니다. 그렇지만 댓글을 달아주시면 최대한 답변드리고자 노력하겠습니다.


※이 글은 프로그래밍 언어에 대한 기초적인 이해를 가정하고 있습니다. 최소 프로그래밍 언어 하나 정도를 약간이라도 접해보시는 것을 추천합니다. 또한, 이 글은 심화 내용은 되도록 피하여 서술했습니다.

 

 

 클래스(Class)는 객체 지향 언에에만 존재하는 독특한 문법입니다.(즉 이번 글에는 순수한 C언어를 다루지 않습니다.) 사실 기본적인 틀은 아직 이 글에서는 다루지 않은 C언어의 구조체와 닮았지만, 해당 문법이 C/C++에만 존재하는 관계로 (실제로는 어떤 언어든 구조체와 비슷한 문법을 구현하는 건 가능합니다.) 먼저 클래스에 대해 짚고 넘어가려고 합니다.

 

 흔히 클래스에 대해 검색하거나 책을 보게 되면, 클래스를 붕어빵 찍는 틀과 같이 '틀'에 비유하는 경우를 볼 수 있습니다. 이는 클래스의 기본적인 특성을 잘 반영하고 있습니다.(물론 완전히는 불가능하겠지만요)

 

이러한 관점에서 클래스는 인스턴스(Instance)라는 붕어빵을 찍어내는 붕어빵 틀이라고 생각할 수 있습니다. 이때, 인스턴스는 메모리에 저장되어  참조가능한 객체(Object)로서 작용하게 됩니다. 이러한 관계는 마치 자료형-변수의 관계와 비슷한 점이 많습니다. 마찬가지로 클래스도 자료형 처럼 사용되기도 합니다. 하지만, 클래스는 그 자체로서 함수나 변수를 포함하는 특징을 가집니다. 이에 관한 용어 정리는 다음과 같습니다.

 

C++ Java/Python
멤버 변수(Member Variable) 속성(Attribute)
멤버 함수(Member Function) 메소드(Method)

 

이 글에서는 Java와 Python의 네이밍을 활용하겠습니다. 일단, 기본적인 클래스의 정의 방식을 알아보겠습니다.

 

class 클래스이름{
    속성 선언들 ;
    메소드 선언들 ;
};

class 클래스이름:
    속성 선언
    메소드 선언

 

보다시피 클래스라는 틀 안에 변수와 함수가 포함되어 있습니다. 이렇게 클래스가 생성되었다면, 다음과 같이 객체를 생성합니다.

//클래스이름 객체이름;
#include <iostream>

using namespace std;

class TestClass{
  int num1 = 0;
  int num2 = 1;
  void printer(int n1){
    cout << num1 << n1 << endl;
  }
};

int main(){
  TestClass test1;
  return 0;
}

 

//클래스이름 객체이름 = new 클래스이름();
public class HelloWorld {
    public static void main(String[] args) {
        TestClass test1 = new TestClass();
    }
}

class TestClass{
  int num1 = 1;
  int num2 = 2;
  void printer(int n1){
    System.out.print(num1);
    System.out.println(n1);
  }
}

#객체이름 = 클래스이름()       (괄호가 없으면 클래스를 대입함!!)
class TestClass:
    num1 = 1
    num2 = 2
    def printer(n1 : int):
        print(str(num1)+str(n1))

 

이런 방식으로 비슷한 형태의 객체를 여러개 찍어낼 수 있습니다. 또한, 이러한 '객체'의 속성, 즉, 인스턴스 변수를 참고하거나, 메소드를 이용하려면 다음과 같은 코드를 이용합니다.

 

객체명.속성
객체명.메소드()

 

객체의 그런데, 여기서 객체의 속성을 참조하려니 다음과 같은 에러가 발생합니다.(C++,Java에서는 에러가 발생합니다. 아래는 C++에서 발생한 에러입니다.)

E:\testpp.cpp:17:9: error: 'int TestClass::num1' is private within this context
test1.num1 =10;
^~~~
E:\testpp.cpp:8:14: note: declared private here
int num1 = 0;
^

 

::이라는 것도 보이고 private이라는 것도 보이는데, 첫번째 것은 클래스 변수를 나타내기 위한 것이므로 에러와는 큰 상관이 없는데, private이라는 것은 외부에서 변수를 참조할 수 없다는 말입니다. 이를 지정하는 것이 접근 지정자입니다.(한편, Python은 에러없이 접근 가능합니다. 이는 기본적으로 가능해서가 아니라 변수 이름 작명법과 관련됩니다.)

 

  C++ Java Python
자신만이 참조 가능 private __으로 시작하는 변수명(_×2)
(단, __으로 끝나면(_×2) public)
외부에서 참조 가능 public 위와 아래의 경우를 제외한 경우

외부에서 참조 불가능
단, 해당 클래스의 인스턴스와 ...

protected

(파생 클래스에서도 가능)

protected

(파생 클래스와 해당 패키지 내)

default

(해당 패키지 내)

_으로 시작하는 변수명(_×1)
(단, __으로 끝나면(_×2) public)

파생 클래스와 패키지라는 새로운 용어가 보이지만, 자세한 설명은 생략하겠습니다.

 

C++에서는 다음과 같이 접근지정자를 지정합니다.

class TestClass{
  public : 
  	int num1 = 0;
  private :
    int num2 = 1;
    int num3 = -1;
  protected :
  void printer(int n1){
    cout << num1 << n1 << endl;
  }
};

 

Java의 경우 다음과 같이 앞에 지정합니다.

class TestClass{
  public int num1 = 1;
  private int num2 = 2;
  public void printer(int n1){
    System.out.print(num1);
    System.out.println(n1);
  }
}

 

아래는 접근 지정자를 활용한 예시입니다.

 

public class HelloWorld {
    public static void main(String[] args) {
        TestClass test1 = new TestClass();
        System.out.println(test1.num2);
        test1.printer(10);
    }
}

class TestClass{
  private int num2 = 2;
}

  에러가 발생하는 코드입니다. 이는 private인 num2를 직접 접근할 수 없기에 생깁니다. 다음의 예시는 어떨까요?

public class HelloWorld {
    public static void main(String[] args) {
        TestClass test1 = new TestClass();
        test1.printer();
    }
}

class TestClass{
  private int num2 = 2;
  public void printer(){
    System.out.print(num2);
  }
}

클래스 내부에선 num2를 접근할 수 있기에 정상적으로 2가 표시됩니다. 

 

다음 글에서는 클래스 변수와 메소드에 관해 좀 더 알아보는 시간을 가지겠습니다. 

 

 

Comments