클래스 생성하기
using System;
namespace ConsoleApp1
{
class Knight
{
public int hp;
public int attack;
public void Move()
{
Console.WriteLine("Move()");
}
public void Attack()
{
Console.WriteLine("Attack()");
}
}
class Program
{
static void Main(string[] args)
{
Knight knight = new Knight();
knight.hp = 100;
knight.attack = 10;
knight.Move();
knight.Attack();
}
}
}
복사, 참조
using System;
namespace ConsoleApp1
{
// class는 ref를 넘긴다
class Knight
{
public int hp;
public int attack;
public void Move()
{
Console.WriteLine("Move()");
}
public void Attack()
{
Console.WriteLine("Attack()");
}
}
// struct는 복사본을 넘긴다
struct Mage
{
public int hp;
public int attack;
}
class Program
{
static void KillMage(Mage mage)
{
mage.hp = 0;
}
static void KillKight(Knight knight)
{
knight.hp = 0;
}
static void Main(string[] args)
{
/* Case 1 */
Knight knight = new Knight()
knight.hp = 100;
knight.attack = 10;
Mage mage = new Mage();
mage.hp = 100;
mage.attack = 10;
KillKight(knight);
KillMage(mage);
Console.WriteLine(knight.hp); // 0
Console.WriteLine(mage.hp); // 100
/* Case 2 */
Mage mage2 = mage;
mage2.hp = 0;
Knight knight2 = knight;
knight2.hp = 0;
Console.WriteLine(knight.hp); // 0
Console.WriteLine(mage.hp); // 100
// 역시 struct는 복사가 된다.
만약 class가 복사되길 원한다면
class Knight
{
public int hp;
public int attack;
// 깊은 복사를 이용하자
public Knight Clone()
{
Knight knight = new Knight();
knight.hp = hp;
knight.attack = attack;
return knight;
}
// ...
}
스택과 힙
- 스택 : 불안정하고 임시적으로 사용됨(함수내부 변수사용에 사용)
- struct로 선언된 객체
- 힙 : 동적할당으로 선언된 변수
- class로 선언된 객체
생성자
class Knight
{
public int hp;
public int attack;
// 기본 생성자
public Knight()
{
hp = 100;
attack = 10;
}
public Knight(int hp)
{
this.hp = hp;
attack = 10;
}
public Knight(int hp, int attack) : this() /*기본생성자를 먼저 호출해달라*/
{
this.hp = hp;
attack = attack;
}
// ...
}
static
class Knight
{
// 내부 변수를 필드라 하며 필드는 각 오브젝트마다 다를 수 있다.
public int hp;
public int attack;
public Knight()
{
hp = 100;
attack = 10;
}
}
class Program
{
static void Main(string[] args)
{
// 각 오브젝트의 필드는 모두 다를수 있음
Knight knight1 = new Knight();
Knight knight2 = new Knight();
Knight knight3 = new Knight();
Knight knight4 = new Knight();
class Knight
{
static public int a;
// static으로 선언시 하나만 존재(오브젝트마다 다르지 않음)
public int hp;
public int attack;
// ...
함수의 static도 동일하게 오브젝트에 종속적이지 않고 클래스에 종속적
class Knight
{
// ...
static public void Test()
{
// static 함수 내부에선 필드(내부변수)를 읽고 쓸수없다
}
상속
- OOP : 은닉, 상속, 다형
class Player
{
// ...
public int parentInt;
public Player()
{
Console.WriteLine("Player()");
}
public Player(int a)
{
Console.WriteLine("Player(int)");
}
}
class Mage : Player
{
// ...
public Mage()
{
Console.WriteLine("Mage()");
// Player()
// Mage() 순으로 출력됨
}
}
class Knight : Player
{
// ...
public Knight() : base(100)
{
// Player(int) 호출됨
base.parentInt = 100; // 접근가능
}
}
은닉성
class Knight
{
// 접근 한정자 : public, protected, private
private int hp;
public void SetHp(int hp)
{
this.hp = hp;
}
}
클래스 형식 변환
class Player
{
// ...
}
class Mage : Player
{
// ...
}
class Knight : Player
{
// ...
}
static void Main(string[] args)
{
Knight knight = new Knight();
Mage mage = new Mage();
Player magePlayer = mage; // 자녀 -> 부모는 항상가능
Mage mage2 = (Mage)magePlayer; // 안전한 캐스팅이라 할 수 없다
bool isMage = (magePlayer is Mage); // 체크1
Mage mage3 = magePlayer as Mage;
if(mage3 != null)
{
// 정상 캐스팅
}
}
다형성
class Player
{
// ...
public void Move()
{
Console.WriteLine("Player::Move()");
}
}
class Mage : Player
{
// ...
public new void Move()
{
Console.WriteLine("Mage::Move()");
}
}
static void Main(string[] args)
{
Player p = new Player();
p.Move(); // Player::Move()
Mage m = new Mage();
m.Move(); // Mage::Move()
Player p2 = m;
Mage m2 = p2 as Mage;
if(m2 != null) m2.Move(); // Mage::Move()
// 매번 이런 체크를 해야할까?
}
class Player
{
// ...
public virtual void Move()
{
Console.WriteLine("Player::Move()");
}
}
class Mage : Player
{
// ...
public override void Move()
{
Console.WriteLine("Mage::Move()");
}
}
static void Main(string[] args)
{
Player p = new Player();
p.Move(); // Player::Move()
Mage m = new Mage();
m.Move(); // Mage::Move()
Player p2 = m;
p2.Move(); // Mage::Move()
}
class Mage : Player
{
// ...
public sealed override void Move() // 더 이상 override금지!
{
Console.WriteLine("Mage::Move()");
}
}
문자열
string name = "Harry Potter";
// 찾기
bool found = name.Contains("Harry");
int index = name.IndexOf('P');
// 변형
name = name + "Junior";
name.ToLower();
name.Replace('r', 'l');
// 분할
string[] names = name.Split(new char[]{ ' ' });
name.Substring(5); // 5부터 끝까지