캡슐화
상속
다형성
추상화
객체
Struct AAAA{
~~
}
AAAA a; // 값 타입이기 때문에 그 자체로 값으로 사용할 수 있는 것.
class BBBB{
~~
}
BBBB b = new BBBB(); // 레퍼런스 타입이기 때문에 메모리 공간을 만들고 값을 연결해주는 것.
Player p = new Player();
// Player p : 플레이어라는 객체를 담을 공간
// new Player() : 실제 플레이어 객체
[접근 제한자] [데이터 타입] 프로퍼티명{
get {}
set {}
}
class Person{
private string _name;
private float _hp;
public float HealthPoint{
get { return _hp; }
set {
_hp = value < 0f ? 0f : value;
}
}
}
class Person{
private string _name;
private int _age;
// 프로퍼티 자체에는 접근 가능하지만
// set 부분은 내부에서만 가능하도록 제한한 경우
public string Name{
get { return _name; }
private set { _name = value; }
}
// 유효성 검사
public int Age{
get { return _age; }
set {
if(value >= 0)
_age = value;
}
}
}
class Person{
public string Name { get; set; }
public int Age { get; set; }
public class Animal{
public string Name { get; set; }
public string Age { get; set; }
public void Eat(){
Console.WriteLine("Animal is eating.");
}
public void Sleep(){
Console.WriteLine("Animal is sleeping.");
}
}
public class Dog : Animal{
public void Bark(){
Console.WriteLine("Dog barks.");
}
}
public class Cat : Animal {
public void Meow(){
Console.WriteLine("Cat meows.");
}
// 부모 sleep보다 cat의 sleep을 먼저 사용
// 이렇게 하기 보다는 virtual을 붙여서 override 하는 것이 더 바람직.
// 이 방법은 다형성을 유지하는 방법은 아님. 그냥 재정의 방식임
public void Sleep(){
Console.WriteLine("Cat is sleeping.");
}
}
public class Unit
{
// 자식에서 재정의 가능하도록 virtual 설정
// virtual이 붙으면 실제 형태가 다를 수 있으니 실형태에 재정의 되었는지 확인하도록 함
public virtual void Move(){
Console.WriteLine("두발로 걷기");
}
public void Attack(){
Console.WriteLine("Unit 공격");
}
}
public class Marine : Unit
{
}
public class Zergling : Unit
{
// 저글링을 단일 형태로 쓰면 상관 없겠으나,
// 이 클래스의 부모 클래스로 접근하여 사용할 때는 문제가 생길 수 있음.
public void Move(){
Console.WriteLine("네발로 걷기");
}
// 이렇게 오버라이드하면 부모 클래스에서 호출해도 문제 없음.
public override void Move(){
Console.WriteLine("네발로 걷기");
}
}
static void Main(string[] args){
List<Unit> units = new List<Unit>();
units.Add(new Marine());
units.Add(new Zergling());
for(int i = 0; i < units.count; i++){
units[i].Move();
// 결과 모두 두발 걷기 출력
// 부모 클래스로 접근해서 부모 클래스의 Move()가 더 가까운 것.
// override하면 저글링은 네발 걷기 출력
}
}
// 추상 클래스
public abstract class Shape{
public abstract void Draw();
}
class Circle : Shape{
// 반드시 구현해야하는 추상 메서드
public override void Draw(){
Console.WriteLine("Drawing Circle.");
}
}
class Square : Shape{
// 반드시 구현해야하는 추상 메서드
public override void Draw(){
Console.WriteLine("Drawing Square.");
}
}
static void Main(string[] args){
// Shape s = new Shape(); // 불가능
List<Shape> shapes = new List<Shape>();
shapes.Add(new Circle());
shapes.Add(new Square());
for(int i = 0; i < shapes.count; i++){
shapes[i].Draw();
}
}
class Stack<T>{
private T[] elements;
private int top;
public Stack(){
elements = new T[100];
top = 0;
}
public void Push(T item){
elements[top++] = item;
}
public T Pop(){
return elements[--top];
}
}
static void Main(string[] args){
Stack<int> intStack = new Stack<int>();
intStack.Push(1);
intStack.Push(2);
intStack.Push(3);
Console.WriteLine(intStack.Pop()); // 3
}
class Pair<T1, T2>{
public T1 First { get; set; }
public T2 Second { get; set; }
public Pair(T1 first, T2 second)
{
First = first;
Second = second;
}
public void Display()
{
Console.WriteLine($"First: {First}, Second: {Second}");
}
}
Pair<int, string> pair1 = new Pair<int, string>(1, "One");
pair1.Display();
Pair<double, bool> pair2 = new Pair<double, bool>(3.14, true);
pair2.Display();
static void Divide(int a, int b, out int qu, out int remain){
// a, b는 값을 복사해서 받는 것 -> 변경해도 원본 변수에 영향 x
// out으로 받은 변수들은 참조해서 받은 것 -> 변경하면 원본 변수에도 반영
qu = a / b;
remain = a % b;
}
int quotient, remainder;
Divide(7, 3, out quotient, out remainder);
Console.WriteLine($"{quotient}, {remainder}"); // 출력 결과: 2, 1
// ref 키워드 사용 예시
void Swap(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
int x = 1, y = 2;
Swap(ref x, ref y);
Console.WriteLine($"{x}, {y}"); // 출력 결과: 2, 1