简体   繁体   English

[抽象类] 类型的接口属性可以在 C# 中实现为具体类吗?

[英]Can an interface property of type [abstract class] be implemented as a concrete class in C#?

Perhaps a bit of a weird question.也许是一个有点奇怪的问题。

I have an interface IReservable that describes behaviour to make a objects "reservable".我有一个接口 IReservable,它描述了使对象“可保留”的行为。 A class which implements it must have a list of reservations, and a few methods to handle creating/removing a reservation.实现它的类必须有一个保留列表,以及一些处理创建/删除保留的方法。 The interface declares a list of reservations, which is an abstract class inherited by 2 concrete classes;接口声明了一个保留列表,它是一个抽象类,由2个具体类继承; one for a room and one for a chair (RoomReservation & ChairReservation).一个用于房间,一个用于椅子 (RoomReservation & ChairReservation)。

Both the room and chair classes implement IReservable, and both will always create instances of only one type (Chair -> ChairReservation and Room -> RoomReservation)房间和椅子类都实现了 IReservable,并且它们总是只创建一种类型的实例(Chair -> ChairReservation 和 Room -> RoomReservation)

Is there a way to make it so that IReservable requires there to be a list of Reservations, but the implementation can decide the concrete Reservation?有没有办法让 IReservable 要求有一个 Reservation 列表,但实现可以决定具体的 Reservation?

explained in code:代码中解释:

public interface IReservable
{
    ICollection<Reservation> Reservations { get; set; }
    
    // Rest omitted for brevity
}

public class Room : IReservable
{
    // Can I make this RoomReservation only?
    public ICollection<Reservation> Reservations { get; set; }
}

public class Seat : IReservable
{
    // And can I make this ChairReservation only?
    public ICollection<Reservation> Reservations { get; set; }
}

It isn't necessary to do this, but I still wondered whether or not it was actually possible;没有必要这样做,但我仍然想知道它是否真的可能; since I can't find any examples of it.因为我找不到任何例子。

You could do this by using generics.你可以通过使用泛型来做到这一点。 For example例如

First let's assume you have some classes like this:首先让我们假设你有一些这样的类:

public abstract class Reservation { }

public class ChairReservation : Reservation { }
public class RoomReservation : Reservation { }

Now your interface would change to this, note the type constraint to make sure the reservations are always derived from Reservation :现在您的界面将更改为此,请注意类型约束以确保保留始终来自Reservation

public interface IReservable<TReservation> 
    where TReservation : Reservation
{
    ICollection<TReservation> Reservations { get; set; }
}

And now your Room and Seat classes would be something like this:现在你的RoomSeat类将是这样的:

public class Room : IReservable<RoomReservation>
{
    public ICollection<RoomReservation> Reservations { get; set; }
}

public class Seat : IReservable<ChairReservation>
{
    public ICollection<ChairReservation> Reservations { get; set; }
}

Even though the suggested generic interface technique works, I usually have a hard time dealing with generic interfaces.即使建议的通用接口技术有效,我通常也很难处理通用接口。 One of the advantages of interfaces is polymorphism.接口的优点之一是多态性。 By using a generic interface your different implementations won't have a common base type so you will lose polymorphism.通过使用通用接口,您的不同实现将不会有共同的基类型,因此您将失去多态性。 ie, you can't do this:即,你不能这样做:

IReservable reservable;
reservable = new Room();
reservable = new Seat();
Console.WriteLine(reservable.Reservations.Count);

If you never intended to take advantage of polymorphism, using a generic interface is enough (however, you may ask yourself why you need an interface in this case).如果您从未打算利用多态性,使用通用接口就足够了(但是,您可能会问自己为什么在这种情况下需要接口)。 Otherwise my suggestion is to use two different interfaces, one for reading reservations and one for reading and modifying:否则我的建议是使用两种不同的界面,一种用于阅读预订,一种用于阅读和修改:

interface IReservable
{
    IEnumerable<Reservation> Reservations { get; }
}

interface IReservable<TReservation> : IReservable
    where TReservation : Reservation
{
    new ICollection<TReservation> Reservations { get; }

    // Reservation methods
}

public class Room : IReservable<RoomReservation>
{
    public ICollection<RoomReservation> Reservations { get; }

    IEnumerable<Reservation> IReservable.Reservations => Reservations;
}

And then you will be able to use polymorphism.然后你就可以使用多态了。

I think the best solution here to use generics as @DavidG showed here我认为这里使用泛型的最佳解决方案是@DavidG在这里展示的

But if for some reason you cannot use generics you can use Explicit Interface Implementation但是如果由于某种原因你不能使用泛型,你可以使用显式接口实现

It will be something like this:它会是这样的:

public class Room : IReservable
{
    IEnumerable<Reservation> reservations;
    ICollection<Reservation> IReservable.Reservations { get { return (ICollection<Reservation>)reservations; } set { reservations = value; } }
    public ICollection<RoomReservation> Reservations { get { return (ICollection<RoomReservation>)reservations.Cast<RoomReservation>(); } set { reservations = value; } }
}

public class Seat : IReservable
{
    IEnumerable<Reservation> reservations;
    ICollection<Reservation> IReservable.Reservations { get { return (ICollection<Reservation>)reservations; } set { reservations = value; } }
    public ICollection<SeatReservation> Reservations { get { return (ICollection<SeatReservation>)reservations.Cast<SeatReservation>(); } set { reservations = value; } }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM