3_c#/C#문법

C# 클래스

Mi:sAng 2023. 7. 15. 18:29
더보기

1. 객체지향 프로그래밍
2. 클래스 선언과 객체의 생성
3.생성자와 종료자
4.정적 필드와 메소드
5. 객체 복사하기
6. this 키워드
7.분할 클래스
8.접근한정자
9. is와 as. 클래스의 형식변환
10. 오버라이딩과 다형성
11. 확장메소드
12. 메소드 숨기기
13. 오버라이딩 봉인
14. 읽기 전용 필드
15. 중첩 클래스
16. 구조체
17. 튜플

 

 

 

1. 객체지향 프로그래밍

    *객체지향 프로그래밍 : 코드내의 모든 것을 객체로 표현하고자 하는 프로그래밍 패러다임

 

     *객체는 1)속성2)기능을 갖는다.

      속성=데이터, 기능=메소드

 

     *클래스 : 객체를 만들기 위한 청사진

       클래스가 설계도라면, 객체는 설계도로 만든 제품이다.

       객체는 인스턴스라고도 한다

 

2. 클래스 선언과 객체의 생성

 

    *클래스 선언 기본 형식

class 클래스 이름
{
	//데이터와 메소드
}

    *객체 생성 

        Cat 클래스의 인스턴스로 kitty 인스턴스를 만들었습니다.

        Cat kitty = new Cat(); 이라는 문장에서 Cat()은 생성자라는 메소드이다.

          -생성자는 클래스의 이름과 동일한 이름을 가지며, 객체를 생성하는 역할을 한다.

          -new 키워드는 생성자를 호출해서 객체를 생성하는 데 사용하는 연산자이다. 

 

Class Cat
{
	public string Name;
    public string Color;
    
    public void Meow()
    {
    	Console.WriteLine("{0}, : 야옹", Name);
    }
}

Cat kitty = new Cat(); // 객체 생성

 

3.생성자와 종료자

    * 생성자가 호출되고 소멸할 때는 종료자가 호출된다.

 

    1) 생성자

        생성자는 클래스의 객체를 생성한다. 클래스를 선언할 때 명시적으로 생성자를

        구현하지 않아도 컴파일러에서 생성자를 만들어준다. (기본 생성자라 한다)

 

    2) 종료자

        종료자의 이름은 클래스 이름 앞에 ~ 를 붙인 꼴이다.

        종료자는 생성자와는 달리 매개변수도 없고 한정자도 사용하지 않는다.

        종료자는 직접 호출할 수 없다.

 

4.정적 필드와 메소드

  1) 정적 필드

    *static은 메소드나 필드(클래스 안에 선언한 변수)가 클래스의 인스턴스가

     아닌 클래스 자체에 소속되도록 지정하는 한정자

 

     *static 으로 한정하지 않은 필드는 자동으로 인스턴스에 소속되며, static으로 한정한 필드는 클래스에 소속됨.

 

     *static으로 수식한 필드는 프로그램 전체에 걸쳐 하나밖에 존재하지 않는다. 

      프로그램 전체에 걸쳐 공유해야 하는 변수가 있다면 정적 필드를 이용하면된다.

using System;

class Global
{
	public static int Count =0;
}

class ClassA{
	public ClassA(){
    	Global.Count++;
    }
}
class ClassB{
	public ClassB(){
    	Global.Count++;
    }
}

  2)정적 메소드 

     *정적 메소드도 인스턴스가 아닌 클래스 자체에 소속된다.

      정적 메소드는 클래스의 인스턴스를 생성하지 않아도 호출이 가능한 메소드이다.

class MyClass
{
	public static void Static Method(){
    	//?
    }
}

MyClass.StaticMethod();

  3)정적 메소드가 아닌 메소드는?

      *정적 메소드는 클래스에 소속되지만 정적 메소드가 아니면

       인스턴스에 소속되므로 인스턴스 메소드라함.

 

      *보통 객체 내부의 데이터를 사용해야하는 경우 인스턴스 메소드 선언

      *네부 데이터를 이용할 일이 없는 경우,인스턴스 생성없이 호출할 수

        있도록 메소드를 정적으로 선언함.

 

5. 객체 복사하기

     1)얕은 복사

     2)깊은 복사

 

6. this 키워드

      *this : 객체가 자신을 지칭할 때 사용하는 키워드.

       객체 내부에서는 자신의 필드나 메소드에 접근할 때 this 키워드를 사용한다

using System;

namespace This
{
	class Employee
    {
    	private string Name;
        private string Position;
        
        public void SetName(string Name)
        {
        	this.Name= Name;
        }   
    }
}

7.분할 클래스

      *분할 클래스란 여러 번에 나눠서 구현하는 클래스를 말한다.

       분할 클래스는 클래스의 구현이 길어질 경우 여러 파일에 나눠서 구현할 수 있게 

       함으로써 소스 코드 관리가 편하도록 하는 것.

 

      *partial을 쓸 때 클래스 이름은 동일해야한다.

using System;

namespace PartialClass
{
	partial class MyClass{
    	public void Method1(){
        	//
        }
    }
    partial class MyClass{
    	public void Method2(){
        	//
        }
    }
}

 

 

8.접근한정자

     접근한정자로 수식하지 않은 클래스의 멤버는 무조건 private으로 접근 수준이 자동 지정된다.

접근한정자 설명
public 클래스의 내부/외부 모든 곳에서 접근가능
protected 클래스의 외부에서는 접근할 수 없지만, 파생 클래스에서는 접근이 가능합니다
private 클래스의 내부에서만 접근할 수 있습니다. 파생 클래스에서도 접근이 불가능합니다
internal 같은 어셈블리에 있는 코드에서만, public으로 접근할 수 있습니다. 다른 어셈블리에 있는 코드에서는 private과 같은 수준의 접근성을 가집니다.
protected internal 같은 어셈블리에 있는 코드에서만 protected로 접근할 수 있습니다. 다른 어셈블리에 있는 코드에서는 private과 같은 수준의 접근성 가집니다.
private protected 같은 어셈블리에 있는 클래스에서 상속받은 클래스 내부에서만 접근이 가능합니다.

 

 

9. is와 as. 클래스의 형식변환

     *is : 객체가 해당형식에 해당하는지를 검사하여 그 결과를 bool형식으로 반환

     *as : 형식 변환 연산자와 같은 역할을 합니다. 다만 형식 변환 연산자가 변환에 실패하는 경우 예외를 던지는 반면, 

              as 연산자는 객체 참조를 null로 만든다는 것이 다릅니다.

using System;

namespace TypeCasting{
	class Mammal
    {
    	public void Nurse()
        {
        
        }
    }
	class Dog: Mammal
    {
    	public void Bark()
        {
        	Console.WriteLine("Bark()");
        }
    }
	class Cat: Mammal
    {
    	public void Meow()
        {
        	Console.WriteLine("Meow()");
        }
    }
	class MainApp
    {
    	static void Main(string[] args)
        {
        	Mammal mammal = new Dog();
            Dog dog;
            
            if(mammal is Dog)
            {
            	dog = (Dog)mammal;
                dog.Bark();
            }
            Mammal mammal2=new Cat();
            
            Cat cat= mammal2 as Cat;
            if(cat !=null)
            {
            	cat.Meow();
            }
            Cat cat2=mammal as Cat;
            if(cat2 !=null)
            {
            	cat2.Meow();
            }
            else
            {
            	Console.WriteLine("cat2 is not a Cat");
            }
        }
    }
}

 

 

10. 오버라이딩과 다형성

     *다형성 : 객체가 여러 형태를 가질 수 있다는 것

                     >> 자신으로부터 상속받아 만들어진 파생 클래스를 통해 다형성을 실현

     *virtual - override : 오버라이딩을 할 기존의 메소드가 virtual로 설정되어있어야한다. 내용을 추가.

using System;

namespace Overriding
{
    class Alphbet
    {
        public virtual void Capital() 
        {
            Console.WriteLine("ABC...");
        }
    }

    class DDD : Alphbet { 
        public override void Capital()
        {
            base.Capital();
            Console.WriteLine("Plus D : ABCD....");
        }
    
    }
    class EEE : Alphbet
    {
        public override void Capital()
        {
            base.Capital();
            Console.WriteLine("Plus E : ABCDE...");
        }

    }
    class Program { 
        static void Main(string[] args) 
        {
            Console.WriteLine("1.");
            Alphbet alphbet = new Alphbet();
            alphbet.Capital();

            Console.WriteLine("2");
            Alphbet alphabet2 = new DDD();
            alphabet2.Capital();

            Console.WriteLine("3");
            Alphbet alphabet3 = new EEE();
            alphabet3.Capital();

        }
    
    }
}

 

 

 

11. 확장메소드

     *확장 메소드는 기존 클래스의 기능을 확장하는 기법.

      기반 클래스 물려받아 메소드나 필드등을 추가하는 상속과는 다르다. "확장 메소드는 기존 클래스를 확장"

     *확장 메소드 선언 방법

       1)static 한정자로 수식하여 메소드 선언

       2)첫번째 매개변수는 반드시 this 키워드로 확장하고자 하는 클래스의 인스턴스 이어야함.

       3)그 뒤에 오는 매개변수는 실제로 확장메소드 호출시 입력되는 값.

       확장 메소드는 클래스 하나 만들어서 그 안에서 선언한다. 이때 이 클래스도 static으로 수식해야함.

namespace aaa{
	public static class 클래스 이름
    {
    	public static 반환형식 메소드이름(this 확장하고자하는 클래스나 형식, 매개변수){
        	//내용
        } 
    }
}

 

 

12. 메소드 숨기기

     *메소드 숨기기: CLR에게 기반클래스에서 구현된 메소드를 감추고 파생클래스에서 구현된 메소드만 보여주는 것.

       메소드 숨기기는 파생 클래스 버전의 메소드를 new 한정자로 수식해서 사용할 수 있다.

       이 new 한정자는 생성자 생성과는 다른 것이다.

using System;

namespace Overriding
{
    class Alphbet
    {
        public void Capital() 
        {
            Console.WriteLine("ABC...");
        }
    }

    class DDD : Alphbet { 
        public new void Capital()
        {
            
            Console.WriteLine("Plus D : ABCD....");
        }
    
    }
  
    class Program { 
        static void Main(string[] args) 
        {
            Console.WriteLine("1.");
            Alphbet alphbet = new Alphbet();
            alphbet.Capital();

            Console.WriteLine("2");
            DDD ddd = new DDD();
            ddd.Capital();//DDD에서 구현한 메소드만 나오고 Alphabet의 메소드 내용은 안나옴

           

        }
    
    }
}

 

13. 오버라이딩 봉인

     *클래스가 상속되지 않도록 봉인하듯이 메소드도 오버라이딩하지 못하도록 봉인할 수 있다.

       virtual로 선언된 가상 메소드를 오버라이딩한 버전의 메소드만 가능하다. sealed 키워드 이용.

       오버라이딩 봉인이라는 것은 기존 메소드 하나를 오버라이딩 하면서 생기는 문제를 찾는데 도움되는 기능.

class Alphbet
{
    public virtual void Capital() 
    {
        Console.WriteLine("ABC...");
    }
}

class DDD : Alphbet { 
    public sealed override void Capital()
    {
        
        Console.WriteLine("Plus D : ABCD....");
    }

}

 

14. 읽기 전용 필드

     *읽기 전용 필드는 읽기만 가능한 필드를 말한다. 즉. 클래스나 구조체의 멤버로만 존재할 수 있으며

       생성자 안에서 값을 지정하면 그 후로는 값변경이 불가하다. readonly 키워드로 선언

       읽기 전용 필드는 생성자 안에서만 초기화가 가능.

 

class Ex
{
	private readonly int min;
    private readonly int max;
    public Staaart(int a, int b){
    	min=a;
        max=b;
    }
}

 

 

15. 중첩 클래스

     *중첩 클래스는 클래스 안에 선언된 클래스이다.

       중첩 클래스는 자신이 속한 클래스의 멤버에 자유롭게 접근 가능하다. private도 접근가능.

       이는 일부 은닉성을 무너뜨리지만 프로그래머에게 약간의 표현의 자유를 준다. 

class Alphabet
{
	class Capital
    {
    	//
    }
}

 

16. 구조체

     *클래스는 객체를 추상화하려고 사용하지만, 구조체는 데이터를 담기위한 자료구조의 목적이다.

      클래스는 참조형식(힙에 할당) / 얕은 복사

      구조체는 값형식(스택에 할당) / 깊은 복사 / 값형식이라서 상속 불가

 

     *객체는 속성과 기능으로 구성되고 이는 필드와 프로퍼티에서 정의가능하다. 

       보통 다루던 객체는 상태의 변화를 허용하는 변경가능 객체이다.

       이와 반대로 변경불가능 객체도 있다. 

       변경불가능 객체의 이점은 속성이 바뀔 수 없기 때문에 버그로 인한 값의 오염을 방지할 수 있다.

 

       *구조체에서 중요한 것은 "값"이므로 구조체에서는 변경불가능 설정이 가능하다

         구조체 전체를 readonly로 강제하므로 필드나 프로퍼티 모두 readonly로 설정해야한다.

readonly Struct strr
{
	public readonly int a;// OK
    public int b;// 오류
}

 

 

17. 튜플

    튜플 : 여러 필드를 담을 수 있는 구조체
     형식이름은 없다
     즉석에서 사용할 복합 데이터 형식을 선언할 때 적합합니다.
     튜플은 구조체이므로 값형식
     값형식은 생성된 지역을 벗어나면 스택에서 소멸된다.
     이는 프로그램에 장기적인 부담을 주지않는다는 장점이 있다.

var tuple = (123,456);

//var로 하면 컴파일러가 튜플의 모양보고 직접 형식 결정
//튜플은 괄호 사이에 두 개 이상의 필드 지정하면서 만들어진다.

 

 

    *튜플의 필드에 접근하여 콘솔출력하는 예시

     튜플의 필드 이름을 지정하지 않는 방법

var tuple = (123,456);
Console.WriteLine($"{tuple.Item1}, {tuple.Item2}");// 123, 456 출력

 

    *튜플의 필드 이름을 지정하는 방법 

var tuple = {Name: "박상현", Age: 17}
var (name, age) = tuple; // 분해
Console.WriteLine($"{name},{age}"); // 출력 결과 : 박상현, 17

 

    *특정 필드 무시할 때는 _사용

var tuple = {Name: "박상현", Age: 17}
var (name, _) = tuple; // 분해
Console.WriteLine($"{name}"); // 출력 결과 : 박상현

 

    *즉석에서 튜플 분해

var (name2, age2) = ("a", 12);
Console.WriteLine($"{name2},{age2}"); // 출력결과, a, 12

 

    *필드 이름없는 튜플과 있는 튜플사이의 할당은 수와 형식이 같으면 할당가능

var unnamed = ("a",123);
var named = (Name: "b", Age : 7);

named = unnamed;

 

 

 

 

 

 

 

 

 

 

+)"이것이 C#이다"로 공부중인데 내용 전부 보기엔 힘들다..

 

 

 

 

출처 <a href="https://kr.freepik.com/free-vector/gradient-lo-fi-illustration_25610027.htm#query=lofi&position=3&from_view=keyword&track=sph">Freepik</a>

 

'3_c# > C#문법' 카테고리의 다른 글

C# 프로퍼티  (1) 2024.11.20
C# 메소드 오버로딩 / 오버라이딩  (0) 2024.10.02
C# TXT파일 접근 - StreamReader, StreamWriter  (0) 2023.07.18
C# 예외 처리 : 개념 정리  (0) 2023.07.13
C# 인터페이스 / 추상 클래스  (0) 2023.07.13