형식변환 수행 없이 자식클래스 메소드 호출 지원
부모클래스에서 사용하는 변수명으로 자식클래스에 변수를 선언하는 것
new
키워드를 붙여 새로 선언한다.
class Parent
{
public int a { get; set; } = 1234;
}
class Child : Parent
{
public new string a { get; set; } = "one-two-three-four";
}
class Program {
static void Main(string[] args)
{
Child child = new Child();
Console.WriteLine(child.a); // one-two-three-four
Console.WriteLine(((Parent)child).a); // 1234
}
}
부모클래스에서 사용하는 메소드명으로 자식클래스에 메소드를 선언하는 것
new
키워드를 붙여 새로 선언한다.
class Parent
{
public void A()
{
Console.WriteLine("Parent");
}
}
class Child : Parent
{
public new void A()
{
Console.WriteLine("Child");
}
}
class Program {
static void Main(string[] args)
{
Child child = new Child();
child.A(); // Child
((Parent)child).A(); // Parent
}
}
자식 클래스에서 부모 클래스의 메소드를 재정의 하는 것. 다형성 지원을 위한 핵심 기능
virtual
, 자식클래스 메소드에 override
키워드 사용.class Parent
{
public virtual void Say() { Console.WriteLine("Parent"); }
}
class Child_1 : Parent
{
public override void Say()
{
Console.WriteLine("Child_1");
}
}
class Child_2 : Parent
{
public override void Say()
{
Console.WriteLine("Child_2");
}
}
class Child_3 : Parent
{
public override void Say()
{
base.Say();
Console.WriteLine("Child_3");
}
}
class Program {
static void Main(string[] args)
{
Parent[] items = new Parent[] { new Child_1(), new Child_2(), new Child_3() };
foreach (Parent item in items)
{
item.Say();
// Child_1
// Child_2
// Parent
// Child_3
}
}
}
'재정의된 메소드를 갖고있는 자식객체'를 부모클래스로 형변환하고, Say()를 호출한다.
하이딩 메소드를 갖고있는 객체는 부모클래스의 메소드를 실행한다.
오버라이딩 메소드를 갖고있는 객체는 재정의된 자신의 메소드를 실행한다.
class Parent
{
public virtual void Say() { Console.WriteLine("Parent"); }
}
class Child_Hiding : Parent
{
public new void Say()
{
Console.WriteLine("Child_Hiding");
}
}
class Child_Overriding : Parent
{
public override void Say()
{
Console.WriteLine("Child_Overriding");
}
}
class Program {
static void Main(string[] args)
{
Parent[] items = new Parent[] { new Child_Hiding(), new Child_Overriding() };
foreach (Parent item in items)
{
item.Say();
// Parent
// Child_Overriding
}
}
}
오버라이드한 메소드에 sealed
키워드를 사용할 수 있다.
이 메소드를 포함한 클래스를 상속한 자식은, 이 메소드를 오버라이드 할 수 없다.
class Parent {
public virtual void A() { }
}
class Child : Parent
{
public sealed override void A() { }
}
class ChildChild : Child
{
// 컴파일에러
// public override void A() { }
}
Object클래스의 메소드 중 Equals()
, ToString()
에 대해 살펴보면, virtual메소드로 정의가 되어있다.
즉, Object를 상속하는 클래스에서 오버라이딩 할 수 있다.
public class Object {
public virtual bool Equals() { /* .. */}
public virtual string ToString() { /* .. */}
// ...
}
재정의 예시
public class Gorani
{
public string? Name { get; set; }
public string? ID { get; set; }
public override bool Equals(object? input)
{
Gorani? g = input as Gorani;
if (g == null)
{
return false;
}
else
{
return Name == g.Name;
}
}
public override string ToString()
{
return $"Name : {Name} / ID : {ID}";
}
}
class Program
{
static void Main(string[] args)
{
Gorani a = new Gorani() { Name = "a", ID = "001" };
Gorani b = new Gorani() { Name = "b", ID = "053" };
Console.WriteLine(a.Equals(b));
Console.WriteLine(a.ToString());
Console.WriteLine(b.ToString());
Console.WriteLine(a);
Console.WriteLine(b);
}
}
메소드 뿐 아니라 연산자도 오버로딩 할 수 있다.
아래와 같은 형태로 사용한다.
public static 클래스명 operator 연산자(인수){
return 반환값;
}
아래는 + 연산자를 오버로딩한 예시이다.
public class Gorani
{
public double noisy { get; set; }
public static Gorani operator +(Gorani op1, Gorani op2)
{
return new Gorani() { noisy = op1.noisy + op2.noisy };
}
public override string ToString()
{
return noisy + "DB";
}
}
class Program
{
static void Main(string[] args)
{
Gorani a = new Gorani() { noisy = 53 };
Gorani b = new Gorani() { noisy = 5353};
Gorani c = a + b;
Console.WriteLine(a + b); // 5406DB
Console.WriteLine(c); // 5406DB
}
}