가상이 아닌 방법을 재정의 할 수 있습니까?
비가 상 메서드를 재정의하는 방법이 있습니까? 또는 유사한 결과를 제공하는 것 (원하는 메서드를 호출하는 새 메서드를 만드는 것 외에)?
Microsoft.Xna.Framework.Graphics.GraphicsDevice
단위 테스트를 염두에두고 메서드를 재정의하고 싶습니다 .
아니요, 가상이 아닌 방법은 재정의 할 수 없습니다. 가장 가까운 new
방법은 같은 이름 의 메서드를 만들어 메서드를 숨기는 것이지만 좋은 디자인 원칙을 위반하므로 권장되지 않습니다.
그러나 메서드를 숨겨도 진정한 가상 메서드 호출처럼 메서드 호출의 실행 시간 다형성 디스패치가 제공되지 않습니다. 이 예를 고려하십시오.
using System;
class Example
{
static void Main()
{
Foo f = new Foo();
f.M();
Foo b = new Bar();
b.M();
}
}
class Foo
{
public void M()
{
Console.WriteLine("Foo.M");
}
}
class Bar : Foo
{
public new void M()
{
Console.WriteLine("Bar.M");
}
}
이 예제에서는 두 M
메서드 모두 print 메서드를 호출합니다 Foo.M
. 보시다시피이 접근 방식을 사용하면 해당 개체에 대한 참조가 올바른 파생 형식이지만 기본 메서드를 숨기면 다형성 이 중단 되는 한 메서드에 대한 새로운 구현을 가질 수 있습니다 .
이러한 방식으로 기본 메서드를 숨기지 않는 것이 좋습니다.
나는 C #의 기본 동작을 선호하는 사람들에게 메서드가 기본적으로 비가 상 (Java와 반대)이라는 편에서는 경향이 있습니다. 더 나아가서 클래스도 기본적으로 봉인되어야한다고 말하겠습니다. 상속은 제대로 설계하기 어렵고 가상으로 표시되지 않은 메서드가 있다는 사실은 해당 메서드의 작성자가 메서드를 재정의 할 의도가 없음을 나타냅니다.
편집 : "실행 시간 다형성 디스패치" :
이것이 의미하는 바는 가상 메서드를 호출 할 때 실행 시간에 발생하는 기본 동작입니다. 예를 들어 이전 코드 예제에서 비가 상 메서드를 정의하는 대신 실제로 가상 메서드와 실제 재정의 된 메서드도 정의했다고 가정 해 보겠습니다.
이 경우 호출 b.Foo
하면 CLR은 b
참조가 가리키는 개체 유형을 올바르게 결정 Bar
하고 호출을 M
적절하게 전달합니다 .
당신은 할 수 없습니다.
가상 메서드 만 재정의 할 수 있습니다 . 여기 에서 MSDN을 참조 하세요 .
C #에서 파생 클래스는 기본 클래스 메서드와 이름이 같은 메서드를 포함 할 수 있습니다.
- 기본 클래스 메서드는 가상으로 정의되어야합니다.
If the base class isn't sealed then you can inherit from it and write a new method that hides the base one (use the "new" keyword in the method declaration). Otherwise no, you cannot override it because it was never the original authors intent for it to be overridden, hence why it isn't virtual.
I think you're getting overloading and overriding confused, overloading means you have two or more methods with the same name but different sets of parameters while overriding means you have a different implementation for a method in a derived class (thereby replacing or modifying the behaviour in it's base class).
If a method is virtual, you can override it using the override keyword in the derrived class. However, non-virtual methods can only hide the base implementation by using the new keyword in place of the override keyword. The non-virtual route is useless if the caller accesses the method via a variable typed as the base type as the compiler would use a static dispatch to the base method (meaning the code in your derrived class would never be called).
There is never anything preventing you from adding an overload to an existing class, but only code that knows about your class would be able to access it.
In the case you are inheriting from a non-derived class, you could simply create an abstract super class and inherit from it downstream instead.
Is there any way to override a non-virtual method? or something that gives similar results (other than creating a new method to call the desired method)?
You cannot override a non-virtual method. However you can use the new
modifier keyword to get similar results:
class Class0
{
public int Test()
{
return 0;
}
}
class Class1 : Class0
{
public new int Test()
{
return 1;
}
}
. . .
// result of 1
Console.WriteLine(new Class1().Test());
You will also want to make sure that the access modifier is also the same, otherwise you will not get inheritance down the line. If another class inherits from Class1
the new
keyword in Class1
will not affect objects inheriting from it, unless the access modifier is the same.
If the access modifier is not the same:
class Class0
{
protected int Test()
{
return 0;
}
}
class Class1 : Class0
{
// different access modifier
new int Test()
{
return 1;
}
}
class Class2 : Class1
{
public int Result()
{
return Test();
}
}
. . .
// result of 0
Console.WriteLine(new Class2().Result());
...versus if the access modifier is the same:
class Class0
{
protected int Test()
{
return 0;
}
}
class Class1 : Class0
{
// same access modifier
protected new int Test()
{
return 1;
}
}
class Class2 : Class1
{
public int Result()
{
return Test();
}
}
. . .
// result of 1
Console.WriteLine(new Class2().Result());
As pointed out in a previous answer, this is not a good design principle.
There is a way of achieving this using abstract class and abstract method.
Consider
Class Base
{
void MethodToBeTested()
{
...
}
void Method1()
{
}
void Method2()
{
}
...
}
Now, if you wish to have different versions of method MethodToBeTested(), then change Class Base to an abstract class and method MethodToBeTested() as an abstract method
abstract Class Base
{
abstract void MethodToBeTested();
void Method1()
{
}
void Method2()
{
}
...
}
With abstract void MethodToBeTested() comes an issue; the implementation is gone.
Hence create a class DefaultBaseImplementation : Base
to have the default implementation.
And create another class UnitTestImplementation : Base
to have unit test implementation.
With these 2 new classes, the base class functionality can be overridden.
Class DefaultBaseImplementation : Base
{
override void MethodToBeTested()
{
//Base (default) implementation goes here
}
}
Class UnitTestImplementation : Base
{
override void MethodToBeTested()
{
//Unit test implementation goes here
}
}
Now you have 2 classes implementing (overriding) MethodToBeTested()
.
You can instantiate the (derived) class as required (i.e. either with base implementation or with unit test implementation).
참고URL : https://stackoverflow.com/questions/1853896/is-it-possible-to-override-a-non-virtual-method
'program story' 카테고리의 다른 글
BigInteger의 .isProbablePrime ()의 가능한 사용 사례는 무엇입니까? (0) | 2020.09.22 |
---|---|
ASP : CheckBox에 대한 OnClick 대 OnClientClick? (0) | 2020.09.22 |
배열 대신 객체를 반환하는 이유는 무엇입니까? (0) | 2020.09.22 |
Visual Studio : "빌드 실패, 마지막 성공 여부"다시 활성화 (0) | 2020.09.22 |
자바 스크립트 변수 정의 : 쉼표 대 세미콜론 (0) | 2020.09.22 |