클래스 사용법 기초

클래스의 사용법에 대해 여러번 다루고 있습니다.

 

이게 간단해 보여도 코딩에 익숙하지 않은

사람에게는 익숙해지는데 시간이 소요되니까

클래스 구조를 이해한 후에는 계속 연습해보고

자신만의 클래스를 만들어 보는게 좋습니다.

 

백날 남들이 만든 코드를 보는 것 보다

직접 머리를 짜내서 써본 코드가

학습에 더 효과적입니다. 

따라하는 것도 좋은데 거기서 한 발자국

더 나아가서 그 코드를 변형해보고

자신의 코드로 만들 수 있습니다.

 

어느정도 실습을 마친 후에 다른 사람의

코드를 보면 머리속에서 그림을

그릴 수 있는 단계가 되는데

그 단계까지 가면 이제 코딩이

아주 힘들거나 하진 않을겁니다.

 

그 단계까지 가느냐 마느냐는 상당히

큰 차이가 있습니다. 특히 OOP 프로그래밍에

오면 이거는 현타가 많이 오는데

간단해 보이는 OOP의 문법이지만

뒤로 갈 수록 OOP의 무수한 변형이

나오기 때문에 초기에 기초를 잘

다지는 것이 꼭 필요한 과정입니다.

 

학교시절 수학, 과학과 비슷하다고 보면 됩니다.

뒤에 나오는 내용은 앞쪽의 지식을 전제로

깔기 때문에 앞을 모르면 뒤에서 헤매게 됩니다.

 

어느 학문이나 기초가 중요한데 OOP는

기초가 아니라 중급 정도 난이도입니다.

 

당연히 프로그래밍 기초 없이

OOP부터 배운다면 못배우는 것은

아니지만 오래걸리는 것 입니다.

 

*******

 

 

*참고로 인터넷이건 교재 건 기술 문서를

보다보면 크게 두 부류가 있습니다.

 

첫번째는 StackOverFlow 같이 특정 질문에

바로 답해주는 방식입니다.

 

'C# 에서 Debug 메시지는 어떻게 출력하나요?'

'비주얼 스튜디오의 디버그 모드에서는

디버그 -> 창 -> 출력 을 사용하고

윈도우 앱으로 DebugView 를 사용해서 볼 수 있습니다.'

 

이런 것이 구글 검색의 이점입니다.

 

다른 한 부류는 MSDN 처럼 포괄적으로

이해해야 하는 기술 문서입니다.

 

MSDN에 대한 호불호는 극명하게 갈리는데

사용자의 성향이나 상황에 따라 차이가 있습니다.

성향과 상황이란 것은 보통 개인이 바꾸기

힘든 것이므로 이 논쟁은 끝날 수가 없는데

MSDN이 정말 잘되어 있다고 말하는 사람과

아주 ㅆㄺ 다라고 말하는 사람이 있습니다.

개인의 입장들이지만 세상만사가 그렇듯이

초극단적인 편견은 별로 도움이 안되지 않을까 -

약간의 의심을 해봅니다.

 

MSDN의 방식은 특정 문제 해결보다는

더 많은 이해도를 요구하는데

단점은 당장 닥친 문제 해결에 별로

도움이 안되는 경우가 많고

장점은 잘 이해하면 응용력이 생깁니다.

 

MSDN은 결국 MS의 직원들이 정리한 문서인데

이 회사가 이런 성향의 사람들이 모인 곳이구나

알 수 있습니다. 약간 오픈소스 커뮤니티에서

이런 스타일을 싫어하는 것이 이해가 갑니다.

한글 번역도 대부분 직역이라 그리 좋지

않기 때문에 종종 영어 원문이 더 나을 수도 있습니다.

 

어쨋든 C#을 할려면 MSDN을 읽어야 하는데

확실히 텍스트가 방대한 것도 사실입니다.

누군가에게는 장점일 수 있고

누군가에게는 단점일 수 있는데

C# 언어의 사용자 입장에서는 따라야겠지요.

(절이 싫으면 중이 떠나야 하니까)

 

언어는 아니지만 IT대기업 중에서 문서화가

잘 되어 있는 회사를 꼽자면 아마존, 구글인데요.

 

개인적으로는 아마존 AWS의 문서화가

최고가 아닌가 싶습니다. 괜히 아마존의 수익이

클라우드 사업에서 나오는게 아닌게,

엄청난 문서화 작업이 수십년에 걸쳐 들어갔습니다.

 

어떻게 보면 언어보다 AWS 운영에 관한

내용이 훨씬 복잡해 보이는데 문서화가

잘되어 있어서 대충 따라하면 해결되는게 많습니다.

 

AWS에 관한 문제를 검색해 보면 항상

아마존의 공식문서가 먼저 가득나오는데요.

 

그런 특성도 있을 겁니다. AWS의 사용자들은

프로그래머들도 있지만 일반 IT관리자가

많기 때문에 친절하게 하지 않으면

회사가 다양한 서비스를 제공하는데

문의가 폭주할 테니까 문서를 잘 만들자 -

그게 해결책이 되니까요.

반면 MSDN의 사용자들은 이미 어느정도

숙련된 프로그래머라고 가정하기 때문에

또 MS 제품들(비주얼 스튜디오)에 익숙하다고

가정하고 쓴 내용들이라 MS사 소프트웨어를

의식적으로(?)건 사용하지 않았다면

엄청 불친절하게 느낄 수 있다고 봅니다.

 

그래도 지금 보면 Tutorial 도 그렇고

과거에 비해 많이 신경을 쓰는 것이

느껴집니다. .NET 쪽의 교육 자습서는

최근에도 계속 업데이트 하고 있습니다.

 

암튼 잡설이 길어졌습니다.

바로 클래스 사용법 기초를 복습적으로

좀 더 설명해 보겠습니다.

 

가장 기본적인 예제인 Person 클래스입니다.

 

using System;

namespace ConsoleApp1
{
    
    class Program
    {
        static void Main(string[] args)
        {

            Person p1 = new Person("Mr Anderson",32);

            Console.WriteLine("Person name: " + p1.name);
            Console.WriteLine("Person  age: " + p1.age);

        }
    }

    class Person
    {
        public string name;
        public int age;

        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }
    }
}

namespace 안에 두개의 클래스가 있습니다.

이들은 서로 접근이 가능한데요.

 

접근제어 개념부터 설명하면, class, field, method 등

OOP의 모든 개체는 접근제어자가 있습니다.

건드릴 수 있냐 없냐는 접근제어로 결정됩니다.

 

Program 클래스의 Main 메소드에서

Person 클래스를 소환합니다.

서로 접근이 가능하다는 것은

식별자 영역(scope)이 같다는 말이기도 한데

지금 이 둘은 class 앞에 Default 값을 적용하고 있습니다.

 

비주얼 스튜디오에서 Main 메소드가 있는

class Program 앞에는 private, protected,

protected internal, private protected 로

명시적으로 선언할 수 없다고 나오는데

public 이나 internal 이 허용이 됩니다.

 

같은 Namespace 내에서는 class 에 접근제어자를

붙이지 않아도 서로 Access가 됩니다.

 

단 오버로드한 생성자는 위에서 처럼

public 으로 명시해야 접근이 가능합니다.

 

생성자(constructor)

생성자는 class Person 의 Person() 를 말합니다.

 

이게 new 키워드로 인스턴스를 생성했을 때

실행되는 코드입니다. 생긴 것은 메소드처럼

생겼는데 메소드는 아닙니다.

생성자는 메소드와 달리 리턴값이 없고

객체의 초기화를 위한 코드가 들어갑니다.

 

this 이 키워드를 쓰는 것은 매개변수와

인스턴스의 필드를 구분하기 위해서입니다.

보통은 같은 식별자 이름을 쓰는게 많습니다.

 

생성자는 컴파일러가 기본으로 Person() 을

만들어주는데 내용을 바꿀 수도 있고

저렇게 오버로딩을 합니다.

 

생성자의 의미는... 인스턴스를 처음으로

메모리에 올리고 프로그램에서 사용하려고

초기화 하는 것 입니다.

 

원래 생성자가 있으면 소멸자(destructor)도

나와야 정상인데 C# 구동환경인 .NET 에서는

CLR이란 가상머신이 알아서 소멸자를 호출합니다.

C#이나 자바 처럼 가상머신을 사용하지 않는

C++에서는 소멸자를 직접 호출해야 합니다.

C#에서는 소멸자를 직접 사용할 일이

많이는 없겠지만 뭐든 메모리에 올려놓은 것은

프로그램이 끝나기 전에 소멸시켜야 합니다.

객체들이 올라가있겠지만 그 객체들 중에는

하드웨어 자원을 사용하는 것들도

있을테니 모두 정리해줘야 합니다.

이것들이 소멸자가 하는 일들입니다만,

C#에서는 여러 가지 방법으로 자원을

관리하기 때문에 딱히 소멸자에 신경쓰지 않지만

 

창, 파일 및 네트워크 연결 등의 관리되지 않는 

리소스를 캡슐화하는 경우 종료자를 

사용하여 해당 리소스를 해제해야 합니다

(MSDN의 설명)

 

 

종료자 - C# 프로그래밍 가이드 | Microsoft Docs

 

종료자 - C# 프로그래밍 가이드

C#의 종료자는 가비지 수집기에서 클래스 인스턴스를 수집할 때 필요한 모든 최종 정리를 수행합니다.

docs.microsoft.com

 

필드에 접근

클래스의 필드에 접근하기 위해서는

인스턴스를 생성한 후에 클래스 변수에

도트 연산자(.)를 사용해서 접근합니다.

 

외부에서 필드에 접근하려면

그 필드의 접근자가 public 이어야 합니다.

 

Person p1 = new Person("Mr Anderson", 32);

에서 p1이 클래스 변수이고

 

p1.name 의 형식으로 접근합니다.

C#에는 Property (속성) 이라는 멤버를

제공하는데 그건 자바의 setter getter를

문법으로 만든 것 입니다.

 

Property는 다른 포스팅에서 다룰테니

일단 필드에 접근하려면 public 이어야 한다.

private은 클래스 외부에서 접근이 안된다 -

정도를 이해합니다.

 

메소드 접근

메소드도 필드 처럼 도트연산자 . 를 사용합니다.

 

메소드가 public void PrintInfo() 라고 합니다.

p1.PrintInfo() 로 메소드를 호출합니다.

 

역시 public 이면 외부에서 접근이 가능하고

private은 접근이 안됩니다.

 

생성자 오버로드

생성자는 여러개를 만들수 있습니다.

 

같은 이름의 함수를 시그니처(매개변수)에 따라

여러개 만드는 것을 오버로드라고 합니다.

다양한 초기화를 할 수 있게 해줍니다.

 

    public class Person
    {
        public string name;
        public int age;

        public Person()
        {
            this.name = "John Doe";
            this.age = 40;
        }


        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }
    }

 

스태틱 키워드

C#에서 스태틱(static) 키워드는

맥락에 따라 다른 의미가 있습니다.

 

우선 메소드에 static을 적용해봅니다.

static 메소드는 클래스에 속한 메소드로

인스턴스 없이 사용할 수 있습니다.

 

보통의 메소드는 new 키워드로 인스턴스를

생성해야 사용할 수 있는데 static 메소드는

클래스 이름으로 그냥 사용할 수 있습니다.

 

이것은 생성자를 호출하지 않고

메소드를 사용하는 것이고

static 메소드에서는 다른 인스턴스의 멤버들

(필드, 메소드) 역시 사용할 수 없습니다.

 

 

using System;

namespace ConsoleApp1
{
    
    class Program
    {
        static void Main(string[] args)
        {
            StaticTutorial.sayHello("Mr Lee");
        }
    }

    class StaticTutorial
    {
        public static void sayHello(string name)
        {
            Console.WriteLine("Hello! " + name);
        }
    }
}

[실행결과]

Hello! Mr Lee

 

static 메소드에서 필드를 사용하려면

마찬가지로 static 필드를 쓸 수 있고요.

메소드도 static을 사용해야 합니다.

 

using System;

namespace ConsoleApp1
{
    
    class Program
    {
        static void Main(string[] args)
        {
            StaticTutorial.sayHello("Mr Lee");
        }
    }

    class StaticTutorial
    {
        private static int num = 7;

        public StaticTutorial()
        {
            Console.WriteLine("constructed");
        }

        public static void sayHello(string name)
        {
            Console.WriteLine("Hello! " + name + " "+ num);
            printSomething();
        }

        static void printSomething()
        {
            Console.WriteLine("Something!");
        }
    }
}

[실행결과]

 

Hello! Mr Lee 7
Something!

 

static 메소드를 사용하는 대표적인 BCL

클래스는 Math 입니다.

 

다음은 2의 3승을 계산하는 Pow 메소드입니다.

static 이라서 인스턴스가 필요없습니다. 

Console.WriteLine(Math.Pow(2.0, 3.0));

public static double Pow(double x, double y);

 

System.Runtime.Extensions에서 볼 수 있습니다.

 

*클래스는 여러개의 인스턴스를 만들 수 있습니다.

static 메소드와 static 필드는 클래스를 위한 것이라

하나밖에 없습니다. 인스턴스 참조로는 접근이

안되고 타입 이름(클래스 이름)으로 접근해야 합니다.

 

static 클래스

static 클래스는 static 메소드와 static 필드를

포함할 수 있습니다. 차이점은 static 클래스는

인스턴스를 만들 수 없습니다.

 

Math 클래스도 static입니다.

public static class Math

 

이것의 인스턴스는 만들 수 없습니다.

 

Math math1 = new Math();

 

는 컴파일 오류가 납니다.

객체의 인스턴스를 만들 필요가 없는 경우

혹은 만들지 못하게 할 때 사용합니다.

 

요약

이전 포스팅에 이어서 계속적으로

클래스 기초에 대해서 알아봤습니다.

 

이 클래스 OOP가 많이 어렵습니다.

어려운 이유는 구체적인 뭐가 있는게

아니라 너무 추상적이라서 그렇습니다.

 

이 세상 뭐든지간에 클래스로 만들 수

있다는 것은 반대적으로 무엇을

클래스로 만들어야 하는지

불명확하다는 말과도 같습니다.

 

약간 우리나라의 주입식 교육이

대충 세상을 주입된 지식의 기준으로

보기가 더 쉽기 때문에 그런 부분이

사고가 전환이 잘 안되는게 아닌가

의문도 갖게 되는데요.

 

OOP는 그대로 따라서 만드는 것도

많이 있지만 창조적인 부분도 일부 필요합니다.

 

예를 들어 인간의 뇌를 클래스로 흉내를

내본다던가 - 우주를 클래스로 정의해본다던가

이런 대담한 상상은 좀처럼 안나옵니다.

물론 이거 너무 선넘는거 아닌가? 

그럴 수도 있기에 얌전히 Person, Car 같은

공장식 클래스만 만들면 좀 지루합니다.

 

도구를 어떻게 사용하는가는 전적으로

사용자에게 달려 있습니다.

 

또 한가지는 OOP를 더 잘 이해하려면

C/C++ 의 이해도가 필요합니다.

OOP라고 해도 개념만으로 CPU와 운영체제가

동작하지는 않으니까 컴퓨터 구조를 다루는

C/C++의 깊이가 있으면 좋습니다.

왜 C/C++이냐? C/C++은 하드웨어에 대해

이해하지 못하면 어차피 더 들어가기 어렵습니다.

하드웨어와 운영체제에는 OOP의 원리를

실제 구현하는 바탕이기 때문에

결국은 알아야 하는 부분입니다.

C와 C++ 둘다를 하긴 어려우니까

하나를 택하라면 C++을 많이 추천합니다.

리눅스를 사용한다면 C로 시작해도 좋습니다.

 

C#의 OOP에 대해서는 상속, 다형성,

이벤트 핸들링 등 많은 주제가 남아있습니다.

충분히 OOP의 기초를 다진 다음에

학습하면 아주 어렵거나 하진 않을겁니다.

공유하기

facebook twitter kakaoTalk kakaostory naver band