한 abstract 정자는 대상에 누락되거나 불완전한 구현이 있음을 나타냅니다. 클래스, 메서드, 속성, 인덱서 및 이벤트와 함께 추상 한정자를 사용합니다. 클래스 선언에서 abstract 한정자를 사용하여 클래스가 자체에서 인스턴스화되지 않고 다른 클래스의 기본 클래스로만 사용됨을 나타냅니다. 추상 클래스에서 파생되는 비 추상 클래스는 추상으로 표시된 멤버를 구현해야 합니다.
C# 언어 참조는 가장 최근에 릴리스된 C# 언어 버전을 문서화합니다. 또한 예정된 언어 릴리스의 공개 미리 보기 기능에 대한 초기 설명서도 포함되어 있습니다.
설명서는 언어의 마지막 세 버전 또는 현재 공개 미리 보기에서 처음 도입된 기능을 식별합니다.
팁 (조언)
C#에서 기능이 처음 도입된 시기를 찾으려면 C# 언어 버전 기록에 대한 문서를 참조하세요.
추상 클래스에는 추상 멤버(구현이 없고 파생 클래스에서 재정의되어야 합니다)와 완전히 구현된 멤버(예: 일반 메서드, 속성 및 생성자)가 모두 포함될 수 있습니다. 이 기능을 사용하면 추상 클래스가 공통 기능을 제공하는 동시에 파생 클래스가 특정 추상 멤버를 구현하도록 요구할 수 있습니다.
비고
인터페이스 멤버는 기본적으로 사용됩니다 abstract .
혼합 멤버가 있는 추상 클래스
다음 예제에서는 구현된 메서드와 추상 멤버를 모두 포함하는 추상 클래스를 보여 줍니다.
namespace LanguageKeywords;
public abstract class Vehicle
{
protected string _brand;
// Constructor - implemented method in abstract class
public Vehicle(string brand) => _brand = brand;
// Implemented method - provides functionality that all vehicles share
public string GetInfo() => $"This is a {_brand} vehicle.";
// Another implemented method
public virtual void StartEngine() => Console.WriteLine($"{_brand} engine is starting...");
// Abstract method - must be implemented by derived classes
public abstract void Move();
// Abstract property - must be implemented by derived classes
public abstract int MaxSpeed { get; }
}
public class Car : Vehicle
{
public Car(string brand) : base(brand) { }
// Implementation of abstract method
public override void Move() => Console.WriteLine($"{_brand} car is driving on the road.");
// Implementation of abstract property
public override int MaxSpeed => 200;
}
public class Boat : Vehicle
{
public Boat(string brand) : base(brand) { }
// Implementation of abstract method
public override void Move() => Console.WriteLine($"{_brand} boat is sailing on the water.");
// Implementation of abstract property
public override int MaxSpeed => 50;
}
public class AbstractExample
{
public static void Examples()
{
// Cannot instantiate abstract class: Vehicle v = new Vehicle("Generic"); // Error!
Car car = new Car("Toyota");
Boat boat = new Boat("Yamaha");
// Using implemented methods from abstract class
Console.WriteLine(car.GetInfo());
car.StartEngine();
// Using abstract methods implemented in derived class
car.Move();
Console.WriteLine($"Max speed: {car.MaxSpeed} km/h");
Console.WriteLine();
Console.WriteLine(boat.GetInfo());
boat.StartEngine();
boat.Move();
Console.WriteLine($"Max speed: {boat.MaxSpeed} km/h");
}
}
class Program
{
static void Main()
{
AbstractExample.Examples();
}
}
/* Output:
This is a Toyota vehicle.
Toyota engine is starting...
Toyota car is driving on the road.
Max speed: 200 km/h
This is a Yamaha vehicle.
Yamaha engine is starting...
Yamaha boat is sailing on the water.
Max speed: 50 km/h
*/
이 예제에서 추상 클래스는 다음을 Vehicle 제공합니다.
-
구현된 멤버:
GetInfo()메서드,StartEngine()메서드 및 생성자 - 이러한 멤버는 모든 차량에 공통 기능을 제공합니다. -
추상 멤버:
Move()메서드 및MaxSpeed속성 - 이러한 멤버는 각 특정 차량 유형에 의해 구현되어야 합니다.
이 디자인을 통해 추상 클래스는 공유 기능을 제공하는 동시에 파생 클래스가 차량별 동작을 구현하도록 할 수 있습니다.
추상 클래스에서 파생된 구체적인 클래스
이 예제에서 Square 클래스는 Shape에서 파생되므로 GetArea 구현을 제공해야 합니다.
abstract class Shape
{
public abstract int GetArea();
}
class Square : Shape
{
private int _side;
public Square(int n) => _side = n;
// GetArea method is required to avoid a compile-time error.
public override int GetArea() => _side * _side;
static void Main()
{
var sq = new Square(12);
Console.WriteLine($"Area of the square = {sq.GetArea()}");
}
}
// Output: Area of the square = 144
다음 기능이 있는 추상 클래스:
- 추상 클래스의 인스턴스는 만들 수 없습니다.
- 추상 클래스에는 추상 메서드 및 접근자가 포함될 수 있습니다.
- 추상 클래스에는 파생 클래스에 기능을 제공하는 구현된 메서드, 속성, 필드 및 기타 멤버도 포함될 수 있습니다.
- 두 한정자는 반대의 의미를 가지므로 추상 클래스에서 한정자를 사용할
sealed수 없습니다.sealed한정자를 사용하면 클래스가 상속되지 않고abstract한정자를 사용하려면 클래스가 상속되어야 합니다. - 추상 클래스에서 추상이 아닌 파생 클래스에는 모든 상속된 메서드 및 접근자의 실제 구현이 포함되어야 합니다.
abstract 메서드 또는 속성 선언에서 한정자를 사용하여 메서드 또는 속성에 구현이 포함되지 않음을 나타냅니다.
추상 메서드에는 다음과 같은 기능이 있습니다.
추상 메서드는 암시적으로 가상 메서드입니다.
추상 메서드 선언은 추상 클래스에서만 허용됩니다.
추상 메서드 선언은 실제 구현을 제공하지 않으므로 메서드 본문이 없습니다. 메서드 선언은 세미콜론으로 끝납니다. 예시:
public abstract void MyMethod();구현은 비 추상 클래스의 멤버인 메서드
override에 의해 제공됩니다.형식의 추상 메서드 선언에서 또는
virtual한정자를 사용하는static것은 오류입니다class. 인터페이스에서 선언static abstract및static virtual메서드를 사용할 수 있습니다.선언 및 호출 구문의 차이점을 제외하고 추상 속성은 추상 메서드처럼 동작합니다.
형식의 정적 속성에서 한정자를 사용하는
abstract것은 오류입니다class. 인터페이스 선언에서 선언static abstract하거나static virtual속성을 지정할 수 있습니다.추상 상속된 속성은 한정자를 사용하는 속성 선언을 포함하여 파생 클래스에서 재정의
override할 수 있습니다.
추상 클래스에 대한 자세한 내용은 추상 및 봉인 클래스와 클래스 멤버를 참조하세요.
추상 클래스는 모든 인터페이스 멤버에 대한 구현을 제공해야 합니다. 인터페이스를 구현하는 추상 클래스는 인터페이스 메서드를 추상 메서드에 매핑할 수 있습니다. 예시:
interface I
{
void M();
}
abstract class C : I
{
public abstract void M();
}
다음 예제에서 클래스 DerivedClass 는 추상 클래스 BaseClass에서 파생됩니다. 추상 클래스에는 추상 메서드 AbstractMethod 및 두 개의 추상 속성 X 및 Y가 포함됩니다.
// Abstract class
abstract class BaseClass
{
protected int _x = 100;
protected int _y = 150;
// Abstract method
public abstract void AbstractMethod();
// Abstract properties
public abstract int X { get; }
public abstract int Y { get; }
}
class DerivedClass : BaseClass
{
public override void AbstractMethod()
{
_x++;
_y++;
}
public override int X // overriding property
{
get
{
return _x + 10;
}
}
public override int Y // overriding property
{
get
{
return _y + 10;
}
}
static void Main()
{
var o = new DerivedClass();
o.AbstractMethod();
Console.WriteLine($"x = {o.X}, y = {o.Y}");
}
}
// Output: x = 111, y = 161
앞의 예제에서 다음과 같이 문을 사용하여 추상 클래스를 인스턴스화하려고 하면,
BaseClass bc = new BaseClass(); // Error
컴파일러가 추상 클래스 'BaseClass'의 인스턴스를 만들 수 없다는 오류가 발생합니다. 그럼에도 불구하고 다음 예제와 같이 추상 클래스 생성자를 사용할 수 있습니다.
public abstract class Shape
{
public string Color { get; set; }
// Constructor of the abstract class
protected Shape(string color)
{
Color = color;
Console.WriteLine($"Created a shape with color {color}.");
}
// Abstract method that must be implemented by derived classes
public abstract double CalculateArea();
}
public class Square : Shape
{
public double Side { get; set; }
// Constructor of the derived class calling the base class constructor
public Square(string color, double side) : base(color)
{
Side = side;
}
public override double CalculateArea()
{
return Side * Side;
}
}
public class Program
{
public static void Main(string[] args)
{
Square square = new Square("red", 5);
Console.WriteLine($"Area of the square: {square.CalculateArea()}");
}
}
Shape 클래스가 선언되어 abstract있으므로 직접 인스턴스화할 수 없습니다. 대신 다른 클래스의 청사진 역할을 합니다.
- 추상 클래스의 개체를 만들 수는 없지만 생성자가 있을 수 있습니다. 이 생성자는 일반적으로
protected파생 클래스만 액세스할 수 있습니다. 이 경우Shape생성자는color매개 변수를 사용하고Color속성을 초기화합니다. 또한 콘솔에 메시지를 출력합니다.public Square(string color, double side) : base(color)파트는 기본 클래스의 생성자(Shape)를 호출하고color인수를 전달합니다. - 클래스에서
Shape정의된 생성자는 색을 매개 변수protected Shape(string color)로 사용합니다. 즉, C#은 더 이상 기본 매개 변수 없는 생성자를 자동으로 제공하지 않습니다. 파생 클래스는 식을 사용하여: base(color)기본 생성자를 호출해야 합니다. 기본값을 색protected Shape(string color="green")으로 설정하면 파생 클래스에서: base(color)식을 생략할 수 있습니다. 생성자는protected Shape(string color="green")색을 녹색으로 설정합니다.
C# 언어 사양
자세한 내용은 C# 언어 사양을 참조하세요. 언어 사양은 C# 구문 및 사용법에 대 한 신뢰할 수 있는 소스 됩니다.
참고 항목
.NET