在c#中實現多態性,如何做到最好?

[英]implementing polymorphism in c#, how best to do it?


first question here, so hopefully you'll all go gently on me!

第一個問題在這里,所以希望你們都會輕輕地對我說話!

I've been reading an awful lot over the past few days about polymorphism, and trying to apply it to what I do in c#, and it seems there are a few different ways to implement it. I hope I've gotten a handle on this, but I'd be delighted even if I haven't for clarification.

過去幾天我一直在閱讀關於多態性的很多內容,並試圖將它應用到我在c#中所做的事情,似乎有幾種不同的方法來實現它。我希望我已經掌握了這個,但即使我沒有澄清,我也很高興。

From what I can see, I've got 3 options:

從我所看到的,我有3個選擇:

  1. I can just inherit from a base class and use the keyword 'virtual' on any methods that I want my derived classes to override.
  2. 我可以從基類繼承並在我希望派生類重寫的任何方法上使用關鍵字'virtual'。

  3. I could implement an abstract class with virtual methods and do it that way,
  4. 我可以用虛方法實現一個抽象類,並以這種方式實現,

  5. I could use an interface?
  6. 我可以使用界面嗎?

From what I can see, if I don't require any implementation logic in the base, then an interface gives me the most flexibility (as I'm then not limiting myself with regards multiple inheritance etc.), but if I require the base to be able to do something on top of whatever the derived classes are doing, then going with either 1 or 2 would be the better solution?

從我所看到的,如果我不需要基礎中的任何實現邏輯,那么一個接口給了我最大的靈活性(因為我當然不限制我自己的多重繼承等),但如果我需要基礎為了能夠在派生類正在做的事情之上做一些事情,那么使用1或2將是更好的解決方案?

Thanks for any input on this guys - I have read so much this weekend, both on this site and elsewhere, and I think I understand the approaches now, yet I just want to clarify in a language specific way if I'm on the right track. Hopefully also I've tagged this correctly.

感謝有關這些人的任何意見 - 本周末我已閱讀了很多內容,無論是在本網站還是其他地方,我認為我現在理解這些方法,但我只是想以語言特定的方式澄清如果我在右邊跟蹤。希望我也正確地標記了這一點。

Cheers, Terry

6 个解决方案

#1


An interface offers the most abstraction; you aren't tied to any specific implementation (useful if the implementation must, for other reasons, have a different base class).

界面提供最多的抽象;您不依賴於任何特定的實現(如果由於其他原因,實現必須具有不同的基類,則非常有用)。

For true polymorphism, virtual is a must; polymorphism is most commonly associated with type subclassing...

對於真正的多態性,虛擬是必須的;多態性最常與類型子類化相關聯......

You can of course mix the two:

你當然可以混合兩者:

public interface IFoo {
    void Bar();
}
class Foo : IFoo {
    public virtual void Bar() {...}
}
class Foo2 : Foo {
    public override ...
} 

abstract is a separate matter; the choice of abstract is really: can it be sensibly defined by the base-class? If there is there no default implementation, it must be abstract.

摘要是一個單獨的問題;抽象的選擇確實是:它可以由基類理智地定義嗎?如果沒有默認實現,則它必須是抽象的。

A common base-class can be useful when there is a lot of implementation details that are common, and it would be pointless to duplicate purely by interface; but interestingly - if the implementation will never vary per implementation, extension methods provide a useful way of exposing this on an interface (so that each implementation doesn't have to do it):

當存在許多常見的實現細節時,常見的基類可能很有用,並且純粹通過接口復制是沒有意義的;但有趣的是 - 如果實現永遠不會因每個實現而有所不同,那么擴展方法提供了一種在接口上公開它的有用方法(這樣每個實現都不必這樣做):

public interface IFoo {
    void Bar();
}
public static class FooExtensions {
    // just a silly example...
    public static bool TryBar(this IFoo foo) {
        try {
             foo.Bar();
             return true;
        } catch {
             return false;
        }
    }
}

#2


All three of the above are valid, and useful in their own right. There is no technique which is "best". Only programming practice and experience will help you to choose the right technique at the right time.

以上所有三個都是有效的,並且本身就是有用的。沒有“最好”的技術。只有編程實踐和經驗才能幫助您在合適的時間選擇合適的技術。

So, pick a method that seems appropriate now, and implement away. Watch what works, what fails, learn your lessons, and try again.

因此,選擇一個現在似乎合適的方法,並實施。觀察哪些有效,哪些失敗,吸取教訓,然后再試一次。

#3


Interfaces are usually favored, for several reasons :

接口通常受到青睞,原因如下:

  • Polymorphisme is about contracts, inheritance is about reuse
  • Polymorphisme是關於契約,繼承是關於重用

  • Inheritance chains are difficult to get right (especially with single inheritance, see for instance the design bugs in the Windows Forms controls where features like scrollability, rich text, etc. are hardcoded in the inheritance chain
  • 繼承鏈很難正確(特別是單繼承,請參閱Windows窗體控件中的設計錯誤,其中可滾動性,富文本等功能在繼承鏈中進行了硬編碼

  • Inheritance causes maintenance problems
  • 繼承會導致維護問題

That said, if you want to leverage common functionnality, you can use interfaces for polymorphism (have your methods accept interfaces) but use abstract base classes to share some behavior.

也就是說,如果你想利用常見的功能,你可以使用接口進行多態(讓你的方法接受接口),但使用抽象基類來共享一些行為。

public interface IFoo
{
    void Bar();
    enter code here
}

will be your interface

將是你的界面

public abstract class BaseFoo : IFoo
{
    void Bar
  {
        // Default implementation
  }
}

will be your default implementation

將是您的默認實現

public class SomeFoo : BaseFoo
{

}

is a class where you reuse your implementation.

是一個重用您的實現的類。

Still, you'll be using interfaces to have polymorphism:

不過,您將使用接口來實現多態:

public class Bar
{
   int DoSometingWithFoo(IFoo foo)
{

    foo.Bar();
}
}

notice that we're using the interface in the method.

注意我們正在使用方法中的接口。

#4


The first thing you should ask is "why do I need to use polymorphism?", because polymorphism is not and end by itself, but a mean to reach an end. Once you have your problem well defined, it should be more clear which approach to use.

你應該問的第一件事是“為什么我需要使用多態?”,因為多態性本身並不是結束,而是達到目的的意思。一旦您明確定義了問題,就應該更清楚地使用哪種方法。

Anyway, those three aproaches you commented are not exclusive, you still can mix them if you need to reuse logic between just some classes but not others, or need some distinct interfaces...

無論如何,你評論的這三個方法並不是獨占的,如果你需要在一些類之間重用邏輯而不是其他類,或者需要一些不同的接口,你仍然可以混合它們......

#5


  • use abstract classes to enforce a class structure
  • 使用抽象類來強制執行類結構

  • use interfaces for describing behaviors
  • 使用接口來描述行為

#6


It really depends on how you want to structure your code and what you want to do with it.

這實際上取決於您希望如何構建代碼以及您希望如何使用它。

Having a base class of type Interface is good from the point of view of testing as you can use mock objects to replace it.

從測試的角度來看,具有Interface類型的基類是很好的,因為您可以使用模擬對象來替換它。

Abstract classes are really if you wish to implement code in some functions and not others, as if an abstract class has nothing other than abstract functions it is effectively an Interface.

如果您希望在某些函數中實現代碼而不是其他函數,那么抽象類就是如此,就像抽象類只有抽象函數一樣,它實際上是一個接口。

Remember that an abstract class cannot be instantiated and so for working code you must have a class derived from it.

請記住,抽象類無法實例化,因此對於工作代碼,您必須具有從中派生的類。

In practice all are valid.

實際上所有都是有效的。

I tend to use an abstract class if I have a lot of classes which derive from it but on a shallow level (say only 1 class down).

我傾向於使用抽象類,如果我有很多類派生自它,但是在淺層(比如說只有1個類)。

If I am expecting a deep level of inheritence then I use a class with virtual functions.

如果我期待深層次的繼承,那么我使用具有虛函數的類。

Eitherway it's best to keep classes simple, along with their inheritence as the more complex they become the more likelyhood of introducing bugs.

無論如何,最好保持簡單的類,以及它們的繼承性,因為它們越復雜,它們就越有可能引入錯誤。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/06/01/7202752d56ecb9eb6c421a900ea59459.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com