C# - 我应该使用什么,接口、抽象类还是两者?
因此,假设我正在用 C# 构建某种房地产应用程序。对于每种类型的财产,我将创建一个类,例如 ResidentialProperty 和 CommercialProperty。这两个类以及所有其他属性类将共享一些公共属性,例如 Id、标题、描述和地址信息。
我希望能够做的是:
a) 返回仅包含基本信息的对象集合
b) 能够调用 GetProperty(id) 等方法,该方法将创建并返回 ResidentialProperty 或 CommercialProperty,或者调用 GetProperties(),该方法将返回其中之一或两者的集合。
因此,创建一个名为 BasicProperty(或 PropertyBase)的抽象类可能是有意义的,它包含所有公共属性,并从它扩展 ResidentialProperty 和 CommercialProperty。这将解决问题 #1,因为我可以创建一个返回 BasicProperties 集合的方法。
但对于#2,能够返回一种属性类型或另一种属性类型,我需要一个接口(IProperty),并让住宅和商业类继承它,然后让 GetProperty(id) 和 GetProperties() 返回IProperty 对象(或者因为它们继承自 IProperty,我可以按原样返回它们而不是作为接口吗?)?
现在,如果我应该使用接口,我该如何处理 BasicProperty 类?
- 我是否将其保留为抽象并实现接口?或者
- 我是否将其保留为抽象并且所有 3 个类都实现该接口?或者
- 我不是将其创建为抽象,将所有基本信息放入接口中,并且BasicProperty、ResidentialProperty和CommercialProperty都实现该接口吗?
提前致谢, 卡尔·J。
So, hypothetically, I'm building some sort of real estate application in C#. For each type of property, I'm going to create a class such as ResidentialProperty and CommercialProperty. These two classes as well as all other property classes will share some common properties, such as Id, Title, Description, and Address information.
What I would like to be able to do is:
a) return a collection of objects that contain just the basic information
b) be able to either call a method such as GetProperty(id) which will create and return either a ResidentialProperty or CommercialProperty, or call GetProperties() which will return a collection of one or the other, or both.
So with that said, it would probably make sense to create an abstract class called BasicProperty (or PropertyBase) which contains all of the common attributes, and have the ResidentialProperty and CommercialProperty extend from it. This would take care of problem #1, as I could create a method that returns a collection of BasicProperties.
But for #2, being able to return either one property type or the other, I would need an Interface (IProperty), and have the Residential and Commercial classes inherit from it, and then have the GetProperty(id) and GetProperties() return an IProperty object (or because they inherit from IProperty, can I return them as is and not as the Interface?)?
Now if I should use an Interface, what do I do with the BasicProperty class?
- Do I leave it as an abstract and implement the Interface? Or
- Do I leave it as an abstract and all 3 classes implement the Interface? Or
- Do I not create it as an abstract, put all of the basic information into the Interface, and the BasicProperty, ResidentialProperty and CommercialProperty all implement the Interface?
Thanks in advance,
Carl J.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
虽然我觉得从一开始就定义一个接口几乎总是一个好主意,只是因为它有助于您的代码在未来变得灵活,但听起来在这种情况下您实际上并没有 >需要这样做。您的
GetProperty
和GetProperties
方法可以使用抽象基类作为返回值。可以这样想:如果我有一个名为
GetShape
的方法会怎样?它可能会返回一个Shape
,对吗?假设Shape
是一个抽象基类,一些派生类是Triangle
、Square
、Circle
等。但是三角形是一种形状,正方形是一种形状,等等——每一个都不仅仅是一种形状 ,但它们仍然是形状。因此,如果我说“给我一个形状”,而你递给我一个正方形,那么你就按照我的要求做了。那里没有什么有趣的事情。
这是 OOP 的核心基本原则之一:派生类的实例是其基类的实例;它只是还更多。
While I feel that defining an interface to begin with is almost always a good idea, just because it helps your code to be flexible in the future, it sounds like in this case you don't actually need to do that. Your
GetProperty
andGetProperties
methods can use your abstract base class as a return value.Think of it like this: What if I had a method called
GetShape
? It would presumably return aShape
, right? Let's sayShape
is an abstract base class, and some derived classes areTriangle
,Square
,Circle
, etc.But a triangle is a shape, a square is a shape, and so on--each of these happens to be more than just a shape, but they are shapes nonetheless. So if I say "give me a shape" and you hand me a square, you're doing just as I asked. No funny business there.
This is one of the core underlying principles of OOP: an instance of a derived class is an instance of its base class; it's just also more than that.
据我所知,你在这里谈论的是两件不同的事情。
数据访问您认为应该创建一个抽象类来包含公共属性是正确的,这就是继承的用途:)(除其他外)
但我不明白为什么您不能创建数据访问具有方法
GetProperty(id)
的类,该方法指定PropertyBase
返回类型,即
public PropertyBase GetProperty(long id)
在 < 实现中code>GetProperty 您可以构造一个
ResidentialProperty
或CommercialProperty
(基于您想要的业务/数据库逻辑)然后返回它,c# 允许您这样做。或许是我没理解你的意思?
HTH
编辑::
From what I can gather, you are talking about two different things here.
You are correct in thinking that you should create an abstract class to contain the common properties, that's what inheritance is for :) (among other things)
But I dont see why you can't create a data access class that has a method
GetProperty(id)
that specifies a return type ofPropertyBase
i.e.
public PropertyBase GetProperty(long id)
in the implementation of
GetProperty
you can construct aResidentialProperty
orCommercialProperty
(based on what ever business/database logic you want) then return it, c# allows you to do that.Perhaps I miss-understood you?
HTH
EDIT::
抽象类用于提供通用行为。接口用于提供一组特定的方法和属性,无论它们的行为如何。
如果您的 ResidentialProperty 和 CommercialProperty 提供了一些常见的行为,那么在抽象类中实现此行为并让它们都从此类继承可能是有意义的。想必它们也会有一些自定义行为,否则不需要子类化,只需有一个 PropertyType 属性来描述实例是哪种类型的 Property 就足够了。
然后,您可以提供您认为有用的任意多个接口:IPropertyBase、IResidentialProperty 和/或 ICommercialProperty。这实际上取决于您是否希望将此库用作其他实现的基础,这些实现可能与您的一个或多个类具有相同的接口,但与您的基本抽象类具有不同的行为。公开代表类型的接口的另一个好处是更容易模拟单元测试。
不可能绝对回答这个问题,因为这实际上取决于您的对象可能如何使用,但我希望这个答案为您提供有用的指导。
An abstract class is used to provide common behaviour. An interface is used to provide a specific set of methods and properties, regardless of how they behave.
If your ResidentialProperty and CommercialProperty provide some common behaviour then it probably makes sense to implement this behaviour in an abstract class and have each of them inherit from this class. Presumably they also will have some custom behaviour ,otherwise there is no need to sub-class, it would then be sufficient just to have a PropertyType property to describe which type of Property the instance is.
You can then provide as many interfaces as you feel would be useful, IPropertyBase, IResidentialProperty and/or ICommercialProperty. It really depends on whether you expect this library to be used a base for other implementations which may have the same interface as one or more of your classes, but not the same behaviour as your base abstract class. The other benefit of exposing interfaces which represent your types is easier mocking for unit testing.
It's not really possible to answer this question absolutely because it really depends on how your objects are likely to be used, but I hope this answer provides you with a useful guideline.
我认为你应该避免使用抽象类,除非它绝对有意义。
许多常见行为可以通过聚合、使用组件赋予您的实体,并且您可以通过使用接口来公开此行为。
我倾向于走这条路的原因是,一旦你有了一个抽象基类,你就必须使用它,因为你不能有多重继承。
迟早,您最终会遇到这样的情况:您确实想要多重继承,但您却被搞砸了。
并不是说我对此持强硬态度,因为我们的许多代码库确实使用了上述的基本抽象类,但是这些实现了接口,并且在这些类上执行的所有代码都通过它们进行通信接口,因此我们可以在必要时将基类切换为更灵活的东西。
It is my opinion that you should avoid using abstract classes unless it absolutely makes sense you should.
A lot of the common behaviour can be given to your entities through aggregation, using components and you can publicise this behaviour through the use of interfaces.
The reason I tend to go down this route, is that once you have an abstract base class, you're tied to using it, as you can't have multiple inheritance.
Sooner or later, you end up with a situation in which you DO want multiple inheritance and you're screwed.
Not that I'm a hardliner on this, because plenty of our code-base does utilise base abstract classes for the above, but those implement the interfaces and all the code enacting on those classes talk to them through the interfaces, so we can switch out the base classes for something more flexible later if necessary.
快速介绍一下我所看到的差异。即使您实现接口,也始终可以使用抽象基类。接口并不能帮助您避免代码重复,而您应该这样做(请参阅 DRY 原则),但是它不会强迫您从任何特殊的东西派生,这使得它们更容易与其他基类或接口结合。
另一方面,抽象基类可以删除一些重复,并且更容易更改基类中的某些内容,而无需触及派生类。当您实现其他人使用的类库时,后者非常好。如果您更改库中接口中的内容,则该接口的所有实现都需要更改!如果您只与一小部分开发人员一起实现应用程序,这可能是一个非常小的问题。但正如其他人所说,基类迫使您从它派生,然后如果出现这种需要,您就无法从其他东西派生。
A quick not about the difference as I see it. You can always use an abstract base class even when you implement interfaces. Interfaces does not help you avoid code duplication which you should (see the DRY principle) but it doesn't force you to derive from anything special which makes them easier to combine with other base classes or interfaces.
An abstract base class on the other hand can remove some duplication and it is easier to change some things in the base without touching the derived classes. The latter is very nice when you implement a class library that others use. If you change things in interfaces in a library, all implementations of that interface needs to change! This might be a very small problem if you only implement an application with a small group of developers. But as other has said, a base class forces you to derive from it and then you cannot derive from something else if that need should appear.
不要将您的基类或接口称为 BasicProperty 或 PropertyBase,只需将其称为 Property。您不会同时拥有财产和基本财产,对吗?您将使用属性类或接口进行操作。
抽象类与接口几乎相同,不同之处在于抽象类可以在字段变量中存储状态。当您的属性具有存储地址之类的数据时,带有字段的抽象类是实现此目的的一种方法。
现在,类的子类化是 OOD 的图画书示例之一,但是除此之外还有其他区分对象的方法,请查看装饰器和行为模式。仅当需要重写基类的方法时才应该子类化。例如,看看这个。
Don't call your base class or interface BasicProperty or PropertyBase, just call it Property. You will not have both a Property and a BasicProperty, will you? You will act with Property classes or interfaces.
An abstract class is almost the same as an interface with the difference that the abstract class can store state in field variables. When your Properties have data like the address that is stored an abstract class with a field is one way to do that.
Now the subclassing of a class is one of the picture book examples of OOD, but there are other ways of differentiating objects than that, look at the decorator and behavior patterns. You should subclass only if you need to override methods of the base class. Have a look at this for example.