C#에서 추상 정적 메서드를 사용할 수 없는 이유는 무엇입니까?

StackOverflow https://stackoverflow.com/questions/3284

  •  08-06-2019
  •  | 
  •  

문제

나는 함께 일해 왔습니다 공급자 최근에 저는 추상 정적 메서드가 있는 추상 클래스를 갖고 싶은 흥미로운 상황을 접했습니다.이 주제에 대한 몇 가지 게시물을 읽었는데, 나름 이해가 됐지만, 명확하고 좋은 설명이 있나요?

도움이 되었습니까?

해결책

정적 메서드는 그렇지 않습니다. 인스턴스화 따라서 객체 참조 없이도 사용할 수 있습니다.

정적 메서드에 대한 호출은 개체 참조가 아닌 클래스 이름을 통해 수행되며, 이를 호출하는 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가 호출됩니다.

만약 당신이 있었다면 수업 유형, 객체가 아닌 유형을 참조하는 변수를 만들 수 있는 Delphi와 마찬가지로 가상 및 추상 정적 메서드(및 생성자)를 더 많이 사용할 수 있지만 사용할 수 없으므로 정적 호출은 불가능합니다. -.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()를 호출하면 어떤 메서드가 호출되나요?어떤 값이 반환되었나요?객체의 인스턴스를 생성하지 않으면 상속이 다소 어렵다는 것을 쉽게 알 수 있습니다.상속이 없는 추상 메서드는 본문이 없어 호출할 수 없는 메서드일 뿐입니다.

또 다른 응답자(McDowell)는 다형성이 객체 인스턴스에서만 작동한다고 말했습니다.그것은 자격을 갖추어야 합니다.클래스를 "클래스" 또는 "메타클래스" 유형의 인스턴스로 처리하는 언어가 있습니다.이러한 언어는 인스턴스 및 클래스(정적) 메서드 모두에 대해 다형성을 지원합니다.

C#은 이전의 Java 및 C++와 같은 언어가 아닙니다.그만큼 static 키워드는 메서드가 동적/가상이 아닌 정적으로 바인딩되었음을 나타내기 위해 명시적으로 사용됩니다.

이전 설명에 추가하기 위해 정적 메서드 호출은 다음 위치에서 특정 메서드에 바인딩됩니다. 컴파일 타임, 오히려 다형성 동작을 배제합니다.

정적 필드와 메서드에 대한 상속이 확실히 필요한 상황은 다음과 같습니다.

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"?

우리는 실제로 (델파이에서) 정적 메서드를 재정의하는데, 이는 약간 보기 흉하지만 우리의 필요에 따라 잘 작동합니다.

클래스가 클래스 인스턴스 없이 사용 가능한 객체 목록을 가질 수 있도록 이를 사용합니다. 예를 들어 다음과 같은 메서드가 있습니다.

class function AvailableObjects: string; override;
begin
  Result := 'Object1, Object2';
end; 

추악하지만 필요합니다. 이렇게 하면 사용 가능한 개체를 검색하기 위해 모든 클래스를 인스턴스화하는 대신 필요한 것만 인스턴스화할 수 있습니다.

이것은 간단한 예이지만 애플리케이션 자체는 단 하나의 서버에서 사용할 수 있는 모든 클래스와 서버에 있는 모든 것이 필요하지 않을 수도 있고 개체 인스턴스가 필요하지 않은 여러 다른 클라이언트가 있는 클라이언트-서버 애플리케이션입니다.

따라서 각 클라이언트에 대해 서로 다른 서버 응용 프로그램을 사용하는 것보다 유지 관리가 훨씬 쉽습니다.

예제가 명확하길 바랍니다.

추상 메서드는 암시적으로 가상입니다.추상 메서드에는 인스턴스가 필요하지만 정적 메서드에는 인스턴스가 없습니다.따라서 추상 클래스에 정적 메서드를 가질 수 있지만 정적 추상(또는 추상 정적)일 수는 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top