최근에 공급자로 꽤 많이 작업하고 있는데, 추상 정적 메서드가 있는 추상 클래스를 갖고 싶은 흥미로운 상황에 직면했습니다. 이 주제에 대한 몇 개의 게시물을 읽었는데 어느 정도 이해가 되긴 했지만 명확한 설명이 있나요?
정적 메서드는 인스턴스화된 메서드가 아니며, 객체 참조 없이 사용할 수 있습니다.
정적 메서드 호출은 객체 참조가 아닌 클래스 이름을 통해 이루어지며, 이를 호출하는 중간 언어(IL) 코드는 추상 메서드를 정의한 클래스 이름을 통해 호출하며, 반드시 사용한 클래스 이름이 아니어도 호출할 수 있습니다.
예를 보여드리겠습니다.
다음 코드가 있습니다:
public class A
{
public static void Test()
{
}
}
public class B : A
{
}
B.Test를 호출하면 다음과 같이 됩니다:
class Program
{
static void Main(string[] args)
{
B.Test();
}
}
그러면 Main 메서드 내부의 실제 코드는 다음과 같습니다:
.entrypoint
.maxstack 8
L0000: nop
L0001: call void ConsoleApplication1.A::Test()
L0006: nop
L0007: ret
보시다시피, 코드를 그렇게 작성할 수 있음에도 불구하고 B.Test가 아닌 A 클래스가 정의했기 때문에 A.Test로 호출됩니다.
델파이에서처럼 객체가 아닌 유형을 참조하는 변수를 만들 수 있는 클래스 유형이 있다면 가상이므로 추상적인 정적 메서드(및 생성자도)를 더 많이 사용할 수 있겠지만, 사용할 수 없으므로 .NET에서는 정적 호출이 가상적이지 않습니다.
IL 설계자가 코드를 컴파일하여 B.Test를 호출하도록 허용하고 런타임에 호출을 확인할 수는 있지만 여전히 일종의 클래스 이름을 작성해야 하므로 여전히 가상이 아닙니다.
가상 메서드, 즉 추상 메서드는 런타임에 다양한 유형의 객체를 포함할 수 있는 변수를 사용할 때만 유용하며, 따라서 현재 변수에 있는 객체에 적합한 메서드를 호출하고 싶을 때만 유용합니다. 정적 메서드를 사용하면 어쨌든 클래스 이름을 거쳐야 하므로 호출할 정확한 메서드는 컴파일 시점에 알 수 있고 변경할 수도 없습니다.
따라서 가상/추상 정적 메서드는 .NET에서 사용할 수 없습니다.
정적 메서드는 상속하거나 재정의할 수 없으므로 추상화할 수 없습니다. 정적 메서드는 클래스의 인스턴스가 아닌 유형에 정의되므로 해당 유형에서 명시적으로 호출해야 합니다. 따라서 자식 클래스에서 메서드를 호출하려면 해당 이름을 사용하여 호출해야 합니다. 이렇게 하면 상속이 무의미해집니다.
잠시 정적 메서드를 상속할 수 있다고 가정해 봅시다. 이 시나리오를 상상해 보세요:
public static class Base
{
public static virtual int GetNumber() { return 5; }
}
public static class Child1 : Base
{
public static override int GetNumber() { return 1; }
}
public static class Child2 : Base
{
public static override int GetNumber() { return 2; }
}
Base.GetNumber()를 호출하면 어떤 메서드가 호출될까요? 어떤 값이 반환될까요? 객체의 인스턴스를 만들지 않으면 상속이 다소 어렵다는 것을 쉽게 알 수 있습니다. 상속이 없는 추상 메서드는 본체가 없는 메서드일 뿐이므로 호출할 수 없습니다.
다른 객체에 대한 응답 (맥도웰) 할 수 있을 것이라고 다형성 때만 인스턴스입니다. 검증함 한다고 지적했다. 같이 가지 않는 언어 치료를 클래스뿐만 인스턴스입니다 " Class"; 또는 " Metaclass"; 유형:. 이러한 언어의 다형성 (정적) 및 클래스용 인스턴스입니다 못하며창조된 지원부에서는 모두 사용할 수 있습니다.
C #, Java, C++ 언어 등 전에 같은 것이 아닙니다. 이 아닌 '정적' 키워드를 사용할 수 있다는 이 방식은 정적으로 바인딩되지 명시적으로 동적임 /가상.
이것은 정적 필드 및 메서드을 상속을 필요한 상황이 말해둘꼐요 있습니다.
abstract class Animal
{
protected static string[] legs;
static Animal() {
legs=new string[0];
}
public static void printLegs()
{
foreach (string leg in legs) {
print(leg);
}
}
}
class Human: Animal
{
static Human() {
legs=new string[] {"left leg", "right leg"};
}
}
class Dog: Animal
{
static Dog() {
legs=new string[] {"left foreleg", "right foreleg", "left hindleg", "right hindleg"};
}
}
public static void main() {
Dog.printLegs();
Human.printLegs();
}
//what is the output?
//does each subclass get its own copy of the array "legs"?
실제로 정적임 오버라이드합니다 it& 조금 있지만, s ugly 서버리스 (의 델파이), # 39 의 작동하잖아 그냥 그랬다고 합니다.
우리가 사용하는 클래스는 클래스 인스턴스 없이 있을 수 있으므로, 예를 들어, 우리는 그들의 객체에는 바뀌엇어요 사용할 수 있는 방법은 다음과 같습니다.
class function AvailableObjects: string; override;
begin
Result := 'Object1, Object2';
end;
그러나 이 는 간단한 예를 들어, 응용 프로그램 자체가 디스크입니다. diskid 사용할 수 있는 클래스는 모든 클라이언트-서버 애플리케이션 서버, 클라이언트 서버 한 수 있는 모든 일을 결코 할 필요가 있으며, 여러 개의 서로 다른 개체의 인스턴스입니다.
이 때문에 다른 것보다 훨씬 더 쉽게 유지할 수 있도록 한 서버 애플리케이션 각 클라이언트입니다.
예를 들어 분명히 있다.