실세계에 존재하는 사물, 혹은 개념을 모델링한 것
-> 건축물의 설계도, 붕어빵 틀
접근제한자 class 클래스명
{
속성 정의; // 프로퍼티
행위 정의; // 함수
}
class AA
{
public int a;
public int b;
private int c;
public void setC()
{
c = 10;
a = 20;
}
public int getC()
{
return c;
}
}
class Program
{
static void Main(string[] args)
{
AA AClass = new AA();
AClass.setC();
Console.WriteLine($"c 값은 {AClass.getC()}");
Console.ReadKey();
}
}
AA : 클래스(붕어빵틀), AClass : 인스턴스(붕어빵)
접근제한자 private 나 기본 설정 시 외부에서 접근 불가(c 는 바로 접근X => setC()로 접근 )
static void Main(string[] args)
{
AA AClass = new AA();
AClass.a = 10;
AA AClass2 = AClass;
AClass2.a = 20;
Console.WriteLine("a 값은 {0}", AClass.a);
Console.ReadKey();
}
=> 출력 시 10 아니라 20이 나옴
ref 함수와 마찬가지로 클래스 참조 시 해당 값이 아닌 주소를 참조
=> AClass.a 와 AClass2.a 가 같은 주소 가리킴
public class Parent
{
public int m_A = 1;
}
public class Child : Parent
{
public int m_A = 10;
public int m_B = 20;
}
class Program
{
static void Main(string[] args)
{
Parent pp = new Parent();
Child cc = new Child();
Parent pcc = (Parent)cc;
Console.WriteLine(cc.m_A);
Console.WriteLine(pcc.m_A);
Console.ReadKey();
}
}
출력
10
1

Child 를 생성하면 그림과 같이 메모리 할당
=> cc.m_A 는 자식 클래스의 변수가 출력

자식 클래스를 부모 클래스로 변환 시 (Parent pcc = (Parent)cc;) 그림과 같이 인식함
(메모리상에는 m_B 가 할당되어 있지만 인식하지 못하고 없는 변수로 나옴)
=> pcc.m_A 출력 시 부모 클래스의 변수가 출력
설계도면(클래스) 에 의해 생성된 객체
-> 메모리 영역에 클래스의 형태로 할당된다.
public AA(int p_a, int p_b, int p_c) // => 생성자
{
a = p_a;
b = p_b;
c = p_c;
}
public AA() // => 기본 생성자
{
a = 10;
b = 20;
c = 30;
}
class Program
{
static void Main(string[] args)
{
AA AClass = new AA(1,2,3);
AA AClass2 = new AA();
Console.WriteLine("AClass의 a 값은 {0}", AClass.a);
Console.WriteLine($"AClass2의 a 값은 {AClass2.a}");
Console.ReadKey();
}
}
=> AClass의 a 값은 1
=> AClass2의 a 값은 10
class AA
{
public int a;
public int b;
private int c;
public static int d;
public static int Add(int p_a)
{
return p_a + AA.d;
}
}
static void Main(string[] args)
{
AA AClass = new AA(1,2,3);
AA AClass2 = new AA();
int result = AA.Add(AClass.a);
Console.WriteLine("a 값은 {0}", AClass.a);
Console.WriteLine($"AClass2의 a 값은 {AClass2.a}");
Console.WriteLine($"AClass의 d 값은 {AA.d}");
Console.WriteLine("계산결과 : {0}", result);
static 의 경우 독립된 저장 공간을 가지고 호출 시 클래스명.변수(메서드)명 식으로 호출
using System;
class ShallowCopyExample
{
public class Person
{
public string Name; // 참조 타입
public int Age; // 값 타입
}
static void Main(string[] args)
{
// 원본 객체 생성
Person person1 = new Person { Name = "Alice", Age = 30 };
// 얕은 복사 수행 => person1 의 주소값이 person2에 전달됨
Person person2 = person1;
// person2의 값을 변경
person2.Name = "Bob"; // 참조 타입 변경
person2.Age = 25; // 값 타입 변경
// 결과 출력
Console.WriteLine($"Person1: Name = {person1.Name}, Age = {person1.Age}");
Console.WriteLine($"Person2: Name = {person2.Name}, Age = {person2.Age}");
}
}
결과
Person1: Name = Bob, Age = 25
Person2: Name = Bob, Age = 25
얕은 복사 시 person1과 person2 가 같은 객체를 참조하게 됨
=> 둘 중 하나만 변경해도 나머지 같이 변경
using System;
class DeepCopyExample
{
public class Person
{
public string Name; // 참조 타입
public int Age; // 값 타입
// 깊은 복사를 수행하는 메서드
public Person DeepCopy()
{
return new Person
{
Name = string.Copy(Name), // 새로운 문자열 복사
Age = Age // 값 타입 그대로 복사
};
}
}
static void Main(string[] args)
{
// 원본 객체 생성
Person person1 = new Person { Name = "Alice", Age = 30 };
// 깊은 복사 수행 => person1 의 실제 값이 person2에 전달
Person person2 = person1.DeepCopy();
// person2의 값을 변경
person2.Name = "Bob"; // 참조 타입 변경
person2.Age = 25; // 값 타입 변경
// 결과 출력
Console.WriteLine($"Person1: Name = {person1.Name}, Age = {person1.Age}");
Console.WriteLine($"Person2: Name = {person2.Name}, Age = {person2.Age}");
}
}
결과
Person1: Name = Alice, Age = 30
Person2: Name = Bob, Age = 25
깊은 복사 시 새 객체를 생성해서 원본 객체의 주소가 아닌 값을 할당하는 방식
=> 원본 객체 값을 변경해도 person2 값은 변하지 않음
부모 클래스가 가지고 있는 기능을 상속받은 자식 클래스에서 사용
public class AA
{
protected int a;
public int b;
}
public class AA1 : AA
{
public int c;
}
public class AA2 : AA1
{
protected void FN()
{
a = 10;
}
public int d;
}
class Program
{
static void Main(string[] args)
{
AA2 AClass = new AA2();
AClass.b = 20;
AClass.a = 1; => 접근제한 때문에 에러
Console.ReadKey();
}
}
클래스명 : 상속받는 클래스명 형태로 선언
자신과 상속받는 클래스 내부에서 사용할 수 있는 접근제한자
=> 변수 a의 경우 AA,AA1,AA2 에서 호출 가능 but main 함수에선 불가능
public class Animal
{
public string Name;
public void Nurse()
{
Console.WriteLine($"{Name} 을 치료");
}
}
public class Dog : Animal
{
public Dog(string p_name)
{
Name = p_name;
}
public void Bark()
{
Console.WriteLine($"{Name} 짖다");
}
}
public class Cat : Animal
{
public Cat(string p_name)
{
Name = p_name;
}
public void meow()
{
Console.WriteLine($"{Name} 울다");
}
}
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog("누렁이");
dog.Nurse();
dog.Bark();
Cat cat = new Cat("나비");
cat.Nurse();
cat.meow();
Animal animal = dog;
// => 자식 타입을 부모 타입으로 형변환 가능, 단 bark 메서드는 사용 불가
Animal animal1 = new Animal();
Dog dog2 = (Dog)animal1; => 부모 타입을 자식 타입으로 변환은 불가능
// 이런식으로 형변환은 가능
animal = dog;
//animal 은 자식인 dog 를 가리키고 있지만 타입이 Animal이라 bark 불가
Dog dog2 = animal as Dog
Console.ReadKey();
}
}
자식 타입에 해당하는 메서드의 주소가 부모 타입에서는 할당되어있지 않아서 문법상 에러는 없지만 실행 시 오류 발생

자식 -> 부모 클래스 형변환 시 Call 함수 호출하면 부모의 메서드가 사용된다. 이 때 자식 클래스의 메서드를 사용하고 싶으면

이런식으로 부모 클래스에 virtual, 자식 클래스에 override 추가
(부모 클래스에서 선언, 자식 클래스에서 재정의)
※ 단 둘의 매개변수와 접근제한자가 같아야 됨
※ 부모 클래스의 call 을 사용하고 싶으면 상속받는 클래스에서 base.call() 로 호출
public class MyClassType
{
public int m_A = 0;
public void Add(int p_a)
{
m_A += p_a;
Console.WriteLine($"덧셈결과 : {m_A}");
}
}
여기서 뺄셈 기능을 추가하고 싶은데 해당 클래스를 건드릴 수 없을 때

static 클래스와 메서드를 추가한 뒤 매개변수에 this 클래스명 변수명 작성
class Program
{
static void Main(string[] args)
{
MyClassType tcls = new MyClassType();
tcls.Add(10);
tcls.Minus(5);
//MyClassType 에는 Add 밖에 없지만 Minus 메서드 사용 가능
Console.ReadKey();
}
}