필드(Field) 만들기
필드(Field)는 클래스의 부품 역할을 하는 클래스의 내부 상태 값을 저장해 놓는 그릇을 말합니다. 예를 들어 필드는 자동차 클래스에 선언되어 있는 변수로 자동차의 부품에 해당한다고 생각할 수 있습니다.
> // 필드(Field): 클래스의 부품 역할을 하는 클래스의 내부 상태 값을 저장해 놓는 그릇
필드(Field)
클래스 안에서 선언된 변수 또는 배열 등을 C#에서는 필드라고 합니다. 필드는 일반적으로 클래스의 부품 역할을 하며, 대부분 private
액세스 한정자(access modifier)가 붙고 클래스 내에서 데이터를 담는 그릇 역할을 합니다. 이러한 필드는 개체의 상태(state)를 보관합니다.
필드는 선언한 후 초기화하지 않아도 자동으로 초기화됩니다. 예를 들어 int
형 필드는 0
으로, string
형 필드는 String.Empty
, 즉 공백으로 초기화됩니다.
지역변수와 전역변수
C#에서 변수를 선언할 때는 Main()
메서드와 같은 메서드 내에서 선언하거나 메서드 밖에서, 즉 메서드와 동등한 레벨에서 변수를 선언할 수 있습니다. 메서드 내에서 선언된 변수 또는 배열을 지역 변수(local variable)라고 하며 메서드 밖에서 선언된 변수를 전역 변수(global variable)라고 부릅니다. 다만, C#에서는 전역 변수라는 용어를 사용하지 않고 메서드와 동일하게 액세스 한정자를 붙여서 필드라고 부릅니다.
지역 변수(Local Variable)
변수는 Main()
메서드가 종료되면 자동으로 소멸됩니다. 변수가 살아 있는 영역은 Main()
메서드의 중괄호 시작({
)과 끝 사이(}
)의 영역입니다. 특정 지역을 범위로 하기에 변수를 일반적으로 지역 변수라고 표현합니다.
다음과 같이 코드를 작성하고 실행해보세요. 3개의 지역 변수 i
, j
, k
를 선언 및 초기화하고 이 값들을 더해서 출력하는 내용입니다. 변수의 값을 덧셈(+
) 기호를 사용하여 합한 후 출력하겠습니다.
예제: 변수 3개 선언 후 덧셈
코드: LocalVariable.cs
using System;
public class LocalVariable
{
public static void Main()
{
int i = 1234;
int j = 2345;
int k = 3456;
Console.WriteLine("{0}", i + j + k); // 7035
}
}
7035
책 초반부에 학습했던 변수 관련 예제를 다시 살펴보았습니다. 변수는 변수가 선언된 블록 안에서만 살아 있습니다. Main()
메서드에서 선언된 변수는 Main()
메서드가 종료되면 자동으로 소멸됩니다.
전역 변수(Global Variable)
Main()
메서드가 아닌 클래스 내에 선언된 변수를 필드라고 합니다. C#에서 필드는 변수와 마찬가지로 주로 소문자 또는 _(언더스코어)로 시작합니다. 이러한 필드는 메서드 내에 선언된 지역 변수와 달리 전역 변수로도 불립니다.
지역 변수와 전역 변수를 만들고 사용하는 예제를 살펴보겠습니다. 다음 코드를 입력한 뒤 실행해보세요.
<예제>지역 변수와 전역 변수 사용</예제>
***코드: ***
// VariableScope.cs
using System;
class VariableScope
{
static string globalVariable = "전역 변수"; // 필드 또는 멤버 변수
static void Main()
{
//[1]
string localVariable = "지역 변수";
Console.WriteLine(localVariable);
//[2][1]
Console.WriteLine(globalVariable); // "전역 변수"
//[2][2]
Test();
}
static void Test() => Console.WriteLine(globalVariable); // "전역 변수"
}
지역 변수
전역 변수
전역 변수
[1]
번 코드는 지역 변수를 선언하고 사용하는 내용입니다.
[2][1]
번 코드는 클래스내에 static
키워드와 함께 전역 변수로 선언된 globalVarialbe
필드를 Main()
메서드에서 사용하는 모습입니다.
[2][2]
번 코드는 필드의 내용을 Main()
메서드가 아닌 Test()
메서드에서 사용하는 예를 보여줍니다.
필드의 종류
필드는 지금까지 다루었던 모든 데이터 형식을 사용할 수 있습니다.
- 변수(variable) 형식의 필드: 지역 변수와 마찬가지로 값을 대입해 사용할 수 있습니다.
- 상수(constant) 형식의 필드: 필드(변수)와 비슷하지만 한 번 값을 초기화한 후 다시 값을 재설정할 수 없습니다. 상수 형식의 필드는 반드시 선언과 동시에 초기화시켜야 합니다.
- 읽기 전용(readonly) 형식의 필드: 필드 중에서
readonly
키워드를 붙이는 읽기 전용 필드도 상수 형식의 필드와 비슷한 역할을 합니다. 단, 상수와 차이점이 있다면 선언 시 초기화시키지 않고 앞으로 배울 생성자로 초기화합니다. - 배열(array) 형식의 필드: 배열을 필드 레벨로 올린 개념으로, 여러 개의 값을 보관할 수 있습니다.
- 기타 개체(object) 형식의 필드: 기타 필드에는 모든 데이터 형식이 올 수 있습니다.
필드 선언 형식
필드를 선언하는 여러가지 모양을 먼저 살펴보겠습니다.
public static int intNum;
- 정적인 정수형 필드 선언
public string strSql;
- 인스턴스 형식의 문자열 필드 선언
public int num;
- 필드도 일반변수처럼 이름을 지음
public string m_name;
- 필드 이름에
m_
접두사를 붙임: 오래된 방식
- 필드 이름에
public string _Age;
- 필드 이름에 _로 시작
표: 필드 선언의 여러 가지 모양
필드 선언 | 설명 |
---|---|
public static int intNum; |
정적인 정수형 필드 선언 |
public string strSql; |
인스턴스 형식의 문자열 필드 선언 |
public int num; |
필드도 일반 변수처럼 이름을 지음 |
public string m_name; |
필드 이름에 m_ 접두사를 붙임 |
public string _Age; |
필드 이름에 _로 시작 |
필드의 기본값
필드의 기본 값은 불 형식은 false
, 숫자 형식은 0
, 그리고 string
과 같은 참조형식은 null
을 가집니다.
필드 이니셜라이저를 사용하여 필드 초기화
클래스 내에 선언된 필드는 자동으로 해당 형식의 기본값으로 초기화됩니다. 예를 들어 정수형(int
, long
, byte
, short
)들은 모두 0
으로 초기화됩니다. 실수형(float
, double
)은 0.0
, 불 형식은 false
그리고 기타 참조형(reference type)은 null
로 초기화됩니다.
앞으로 계속 나오겠지만, 클래스 코드 안에서 this
개체는 해당 클래스의 인스턴스 개체를 참조합니다. this.멤버이름
형태로 사용되어 클래스의 특정 멤버에 접근할 수 있습니다.
이번에는 필드를 선언과 동시에 초기화하는 필드 이니셜라이저를 사용해보겠습니다.
예제: 필드 이니셜라이저 사용
코드: FieldInitializer.cs
using System;
class Say
{
//[1] 필드(멤버 변수)
private string message = "안녕하세요."; // 필드 이니셜라이저
//[2] 메서드
public void Hi()
{
this.message = "반갑습니다.";
Console.WriteLine(this.message);
}
}
class FieldInitializer
{
static void Main()
{
Say say = new Say();
say.Hi();
}
}
반갑습니다.
[1]
번 코드 영역에서 필드를 선언과 동시에 "안녕하세요." 문자열로 초기화했습니다. 필드는 변수와 달리 선언과 동시에 초기화하지 않으면 자동으로 기본값으로 초기화됩니다.
[2]
번 코드 영역에서는 Hi()
메서드에서 this
키워드를 통해서 나 자신의 클래스(Say
)의 인스턴스인 개체의 내부에 선언된 message
필드를 접근해서 새로운 값으로 초기화해서 사용하는 내용을 보여줍니다.
코드: FieldInitializer.java
class Say {
// 필드(멤버 변수)
private String message = "안녕하세요."; // 필드 이니셜라이저
// 생성자
public Say() {
this.message = "반갑습니다."; // 생성자를 사용한 필드 초기화
}
// 메서드
public void hi() {
System.out.println(this.message);
}
}
public class FieldInitializer {
public static void main(String[] args) {
// Say 클래스의 인스턴스 생성
Say say = new Say();
// hi() 메서드 호출
say.hi(); // 반갑습니다.
}
}
반갑습니다.
배열 형식의 필드 사용하기
필드에 배열을 사용해보도록 하겠습니다.
코드: FieldArray.cs
using System;
class Schedule
{
//[1] 필드에 배열 사용
private string[] weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
public void PrintWeekDays()
{
foreach (var day in weekDays)
{
Console.Write($"{day}\t");
}
Console.WriteLine();
}
}
class FieldArray
{
static void Main()
{
Schedule schedule = new Schedule();
schedule.PrintWeekDays();
}
}
Sun Mon Tue Wed Thu Fri Sat
요일 정보를 배열 형식의 weekDays
필드에 저장 후 PrintWeekDays()
메서드에서 반복해서 출력해보는 예제입니다. 이처럼 필드에는 변수, 배열 등의 데이터 구조가 올 수 있습니다.
액세스 한정자(Access Modifier)
필드를 만들고 클래스 외부(다른 클래스)에서 사용하도록 설정하려면 public
액세스 한정자를 붙이거나 뒤에서 자세히 다룰 속성(Property)으로 변환시켜야 합니다.
멤버 보이기(Member visibility)
액세스(접근) 한정자를 통해서 클래스의 '멤버에 대한 보이기(member visibility)' 여부를 적용할 수 있습니다.
액세스 한정자에 대해 간단히 정리하자면 클래스와 클래스의 멤버에는 액세스 한정자를 붙여서 접근에 대한 권한을 설정할 수 있습니다. 아무것도 붙이지 않거나 private
을 붙이면 해당 클래스의 멤버는 해당 파일이나 클래스 영역에서만 사용됩니다. public
을 붙이면 해당 클래스와 멤버에 제한 없이 외부에서도 접근이 가능합니다.
액세스 한정자의 종류
클래스와 클래스간의 멤버 접근시 다음과 같은 액세스 한정자(액세스 한정자)가 적용됩니다. 기본적으로 클래스 또는 클래스의 멤버에 액세스 한정자를 붙이지 않으면 private
한정자로 인식합니다. 다음 내용은 한번 정도 읽어보고 넘어가면 됩니다.
public
: 멤버에 대한 접근이 제한되지 않습니다. 모든 곳에서(Everywhere) 접근이 가능합니다.public
이 지정된 클래스 및 클래스의 멤버는 항상 접근이 가능합니다.private
: 현재 클래스내에서만 접근이 가능합니다. 오직(Only) 해당 클래스내에서만 사용 가능합니다.private
이 지정된 클래스 및 멤버는 해당 클래스에서만 접근이 가능합니다.protected
: 현재 클래스 또는 현재 클래스를 상속하는 자식 클래스에게만 접근이 허가됩니다.protected
가 지정된 클래스 및 멤버는 해당 클래스와 해당 클래스를 상속하는 파생 클래스에서 접근이 가능합니다. 상속을 학습할 때 자세히 다룹니다.internal
: 현재 프로젝트(어셈블리(DLL파일) 내의 모든 클래스에게 접근이 허가됩니다.protected internal
: 현재 어셈블리(DLL파일) 또는 현재 어셈블리에서 파생된 모든 클래스에게 액세스가 허가됩니다.internal
이 지정된 클래스 또는 멤버는 해당 어셈블리(같은 프로그램)에서 접근이 가능합니다.
필드에 public
액세스 한정자 사용하기
클래스내에 선언되는 필드는 대부분 private
키워드가 붙습니다. 하지만, public
키워드를 붙여 클래스 외부에서도 접근 가능하도록 설정이 가능합니다.
코드: PublicField.cs
//[?] public 필드: 필드는 대부분 private으로 구현하지만, public도 가능합니다.
using System;
namespace PublicField
{
class Category
{
// public 필드(멤버 변수;전역 변수)
// public 필드는 앞으로 배울 다음과 같은 방식으로 대체 권장:
// (1) private 필드 + public 속성(Property)
// (2) 자동 속성(Auto Property)으로 구현
public string CategoryName;
}
class PublicField
{
static void Main()
{
Category book = new Category();
book.CategoryName = "책";
Console.WriteLine(book.CategoryName); // 책
}
}
}
책
Category
클래스에 CategoryName
이름의 필드를 생성하고 public
액세스 한정자를 설정했습니다. 이렇게 설정한 필드는 다른 클래스인 PublicField
클래스의 Main()
메서드에서 접근해서 값을 설정하거나 가져갈 수 있습니다. 필드는 거의 대부분 소문자로 시작하지만, public
필드는 속성의 의미를 가지기에 대문자로 표현해 보았습니다.
public
과 private
액세스 한정자
이번에는 private
과 public
을 사용하는 액세스 한정자를 살펴보겠습니다.
코드: PublicAndPrivate.cs
> //[?] 액세스 한정자(Access Modifiers): 접근 권한
> // - public: 공용(제한 없음)
> // - private: 전용(해당 클래스내에서만 접근)
> public class Car
. {
. // 메서드
. public static void Hi() { Console.WriteLine("Hi"); }
. private static void Bye() { Console.WriteLine("Bye"); }
. // 필드
. public static string name; // 이름
. private static int age; // 나이
. // private한 필드를 외부에 공개하고자할 때에는 public한 메서드로 공개
. public static void SetAge(int intAge) { age = intAge; }
. public static int GetAge() { return age; }
. }
>
> //[1] public 멤버는 항상 접근 가능
> Car.Hi();
Hi
>
> //[2] private 멤버는 다른 클래스에서 접근 불가
> Car.Bye();
(1,5): error CS0122: 'Car.Bye()' is inaccessible due to its protection level
>
> //[3] public 필드는 외부에서 접근 가능
> Car.name = "RedPlus"; Console.WriteLine(Car.name);
RedPlus
>
> //[4] public 메서드로 필드의 값을 설정(Set) 및 조회(Get)
> Car.SetAge(21);
> Car.GetAge()
21
이번에는 public
과 private
키워드를 비교해 보겠습니다.
코드: PublicPrivate.cs
using System;
public class TestClass
{
// 필드 선언
// 액세스 한정자(Access Modifier): public, private, protected, ...
// private(비공개): 해당 클래스내에서만 사용
private static string name = "홍길동";
// public(공개;제한없음): 다른 클래스에서도 사용 가능
public static string siteName = "길벗"; // public 필드는 권장하지 않음
// 메서드 선언
public static string GetName()
{
return name;
}
}
class PublicPrivate
{
static void Main()
{
// TestClass.name; -> private 멤버는 외부에 노출되지 않음
Console.WriteLine(TestClass.siteName); // public 멤버는 외부에 노출
// private 필드의 값을 외부에 공개하고자할 때에는 public으로 공개
Console.WriteLine(TestClass.GetName());
}
}
길벗
홍길동
[실습] 여러 가지 형태의 필드 선언, 초기화, 참조
소개
지금까지 지역 변수와 전역 변수, 필드에 대해 살펴보았습니다. 이번 실습을 통해 필드의 여러 가지 사용 예를 살펴보겠습니다.
따라하기
(1) 새로운 C# 콘솔 프로젝트를 다음과 같이 생성합니다.
프로젝트 형식 | 템플릿 | 이름 | 위치 |
---|---|---|---|
Visual C# | 콘솔 응용 프로그램 | FieldNote | C:\C# |
(2) 솔루션 탐색기에서 Program.cs 파일을 FieldNote.cs 파일로 이름을 변경한 후 이미 만들어져 있는 모든 코드를 삭제한 후 다음과 같이 작성합니다.
코드: FieldNote.cs
//[?] 필드(Field): 클래스 안에서 생성된 변수(멤버변수)
using System;
namespace FieldNote
{
class Person
{
//[1] 변수 형식의 필드
private string name = "박용준";
//[2] 상수 형식의 필드
private const int m_age = 21;
//[3] 읽기전용 형식의 필드
private readonly string _NickName = "RedPlus";
//[4] 배열 형식의 필드
private string[] _websites = { "닷넷코리아", "VisualAcademy" };
//[5] 모든 형식의 필드
private object all = DateTime.Now.ToShortTimeString();
public void ShowProfile()
{
string r =
$"{name}, {m_age}, {_NickName}, {String.Join(", ", _websites)}, " +
$"{Convert.ToDateTime(all).ToShortTimeString()}";
Console.WriteLine(r);
}
}
class FieldNote
{
static void Main()
{
Person person = new Person();
person.ShowProfile();
}
}
}
(3) 소스 코드를 다 입력한 후 Ctrl+F5를 눌러 프로그램을 실행하면 명령 프롬프트 창에 다음과 같이 출력됩니다.
박용준, 21, RedPlus, 닷넷코리아, VisualAcademy, 오전 1:57
마무리
필드를 다른 클래스에서 접근하고자 하게 하려면 public
액세스 한정자를 붙이고, 같은 클래스 내에서만 사용하고자 할 때에는 private
액세스 한정자를 붙인다. 다만, 앞으로 책과 강의에서는 필드는 무조건 private
키워드를 붙이는 걸 원칙으로 합니다. 외부에 필드를 공개하고자 할 때는 뒤에서 다룰 속성을 사용해서 공개하는 것이 좋습니다.
장 요약
필드(Field) 클래스/개체의 부품 역할을 하여 임시적으로 데이터를 보관해 놓는 역할을 주로 합니다. 이 책 전체에 걸쳐 필드는 무조건 private
을 기준으로 사용하되, 추후 상속을 배우고 나면 protected
까지 사용할 것입니다. 필드에는 public
키워드를 붙이지 않는 습관을 들여 놓고 필드의 내용을 외부에 공개할 때에는 public
메서드 또는 뒤에서 배울 속성을 사용하는 것이 좋습니다.