기본 유형 " virtual
" 에서 메소드를 선언 한 다음 하위 유형 에서 일치하는 메소드를 선언 할 때 override
단순히 " new
"키워드 를 사용하는 대신 " "키워드를 사용하여 하위 유형에서 메소드 를 대체하는 것의 차이점은 무엇입니까 ?
기본 유형 " virtual
" 에서 메소드를 선언 한 다음 하위 유형 에서 일치하는 메소드를 선언 할 때 override
단순히 " new
"키워드 를 사용하는 대신 " "키워드를 사용하여 하위 유형에서 메소드 를 대체하는 것의 차이점은 무엇입니까 ?
답변:
"new"키워드는 재정의되지 않으며 기본 클래스 메소드와 관련이없는 새 메소드를 나타냅니다.
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
public class Test
{
public static void Main ()
{
Foo test = new Bar ();
Console.WriteLine (test.DoSomething ());
}
}
재정의를 사용하면 true로 인쇄 될 수 있습니다.
(Joseph Daigle에서 가져온 기본 코드)
따라서 당신이 진정한 다형성을하고 있다면 항상 덮어야 합니다. "새"를 사용해야하는 유일한 방법은 메소드가 기본 클래스 버전과 관련이없는 경우입니다.
virtual
베이스와 override
유래에? 왜 존재합니까? 코드는 여전히 실행되지 않습니다. new
순전히 가독성이 좋습니까?
나는 항상 이와 같은 것들을 그림으로 더 쉽게 이해합니다.
다시, 조셉 대글의 코드를 가져 와서
public class Foo
{
public /*virtual*/ bool DoSomething() { return false; }
}
public class Bar : Foo
{
public /*override or new*/ bool DoSomething() { return true; }
}
그런 다음 다음과 같이 코드를 호출하십시오.
Foo a = new Bar();
a.DoSomething();
참고 : 중요한 것은 객체가 실제로 Bar
이지만 변수 유형으로 저장한다는 것입니다Foo
(이것은 캐스팅과 유사합니다)
당신이 사용 여부에 따라 다음과 같이 결과가 될 것입니다 virtual
/ override
또는 new
클래스를 선언 할 때.
다음은 가상 및 비가 상 메소드의 동작 차이를 이해하기위한 코드입니다.
class A
{
public void foo()
{
Console.WriteLine("A::foo()");
}
public virtual void bar()
{
Console.WriteLine("A::bar()");
}
}
class B : A
{
public new void foo()
{
Console.WriteLine("B::foo()");
}
public override void bar()
{
Console.WriteLine("B::bar()");
}
}
class Program
{
static int Main(string[] args)
{
B b = new B();
A a = b;
a.foo(); // Prints A::foo
b.foo(); // Prints B::foo
a.bar(); // Prints B::bar
b.bar(); // Prints B::bar
return 0;
}
}
new
단순히 override를 사용하지 않을 때 왜 기본 메소드를 "숨겨"사용하는 것이 똑같 을까요?
virtual
. 컴파일러는 virtual
서명 이없는 클래스 "bloodline"에서 동일한 함수 이름을 볼 경우 불평합니다
new
키워드는 실제로 해당 특정 유형에 존재하는 완전히 새로운 멤버를 작성합니다.
예를 들어
public class Foo
{
public bool DoSomething() { return false; }
}
public class Bar : Foo
{
public new bool DoSomething() { return true; }
}
이 방법은 두 가지 유형 모두에 존재합니다. 리플렉션을 사용하고 유형의 멤버를 가져 Bar
오면 실제로 DoSomething()
똑같이 보이는 두 개의 메소드가 있습니다. 를 사용 new
하면 기본 클래스에서 구현을 효과적으로 숨길 수 있으므로 클래스가 Bar
(내 예제에서) 파생 될 때 메소드 호출이 아닌 로 base.DoSomething()
이동합니다 .Bar
Foo
virtual / override 는 컴파일러에게 두 가지 방법이 관련되어 있으며 어떤 상황에서는 첫 번째 (가상) 메소드를 호출한다고 생각할 때 실제로 두 번째 (재정의) 메소드를 호출하는 것이 맞다는 것을 컴파일러에게 알려줍니다. 이것이 다형성의 기초입니다.
(new SubClass() as BaseClass).VirtualFoo()
SubClass의 재정의 된 VirtualFoo () 메소드를 호출합니다.
new 는 컴파일러에게 기본 클래스의 메서드와 이름이 같은 파생 클래스에 메서드를 추가하고 있지만 서로 관계가 없다고 알려줍니다.
(new SubClass() as BaseClass).NewBar()
BaseClass의 NewBar () 메서드를 호출합니다.
(new SubClass()).NewBar()
SubClass의 NewBar () 메소드를 호출합니다.
기술적 세부 사항 외에도 가상 / 재정의를 사용하면 디자인에 대한 많은 의미 정보가 전달된다고 생각합니다. 가상 메소드를 선언 할 때 구현 클래스가 기본이 아닌 고유 한 구현을 제공하고자 할 수 있음을 나타냅니다. 마찬가지로 기본 클래스에서 이것을 생략하면 기본 메소드가 모든 구현 클래스에 충분해야한다는 기대를 선언합니다. 마찬가지로 추상 선언을 사용하여 구현 클래스가 자체 구현을 제공하도록 할 수 있습니다. 다시 말하지만, 이것은 프로그래머가 코드 사용을 어떻게 기대하는지에 대해 많은 의사 소통을한다고 생각합니다. 기본 클래스와 구현 클래스를 모두 작성하고 new를 사용하여 자신을 발견하면 부모에서 메소드를 가상으로 만들지 않고 내 의도를 구체적으로 선언하지 않기로 한 결정을 진지하게 다시 생각할 것입니다.
내 버전의 설명은 속성 을 사용 하여 차이점을 이해하는 데 도움이됩니다.
override
충분히 간단 하죠? 기본 유형 은 상위 유형을 대체 합니다.
new
아마도 오해의 소지가 있습니다. 속성을 사용하면 이해하기 쉽습니다.
public class Foo
{
public bool GetSomething => false;
}
public class Bar : Foo
{
public new bool GetSomething => true;
}
public static void Main(string[] args)
{
Foo foo = new Bar();
Console.WriteLine(foo.GetSomething);
Bar bar = new Bar();
Console.WriteLine(bar.GetSomething);
}
당신이이 알 수있는 디버거를 사용하여 Foo foo
이 이 개 GetSomething
실제로 재산의 두 버전이 같은 특성을 Foo
의와 Bar
의를하고, 알고있는 사용 하나, C #을 "추천"현재 유형에 대한 속성입니다.
Bar 버전을 사용하려면 override를 사용하거나 Foo foo
대신 사용했을 것입니다.
Bar bar
완전히 새로운 동작을 원하기 때문에 1 만 있습니다.GetSomething
어떤 방법으로 메소드를 표시하지 않는 것은 다음을 의미합니다. 런타임 유형이 아닌 오브젝트의 컴파일 유형을 사용하여이 메소드를 바인드하십시오 (정적 바인딩).
다음과 같은 방법으로 메소드 표시 virtual
: 컴파일 시간 유형 (동적 바인딩)이 아닌 오브젝트의 런타임 유형을 사용하여이 메소드를 바인드하십시오.
파생 클래스에서 기본 클래스 virtual
메서드를 표시 override
한다는 것은 다음을 의미합니다. 이는 개체의 런타임 유형 (동적 바인딩)을 사용하여 바인딩 할 메서드입니다.
파생 클래스에서 기본 클래스 virtual
메서드를 표시하는 것은 다음을 new
의미합니다. 이것은 기본 클래스에서 이름이 같은 메서드와 관련이없는 새로운 메서드이며 객체의 컴파일 시간 유형 (정적 바인딩)을 사용하여 바인딩해야합니다.
virtual
파생 클래스에서 기본 클래스 메서드를 표시하지 않으면 다음을 의미합니다.이 메서드는 new
(정적 바인딩) 으로 표시됩니다 .
메소드를 표시하는 것은 다음을 abstract
의미합니다.이 메소드는 가상이지만 본문을 선언하지 않으며 클래스도 추상적입니다 (동적 바인딩).
new
하면 "사용 하면 이름이 같은 새 멤버가 만들어지고 원래 멤버가 숨겨override