Java 为什么要使用继承呢?
我知道这个问题一直存在,但似乎总是基于这样的假设,即继承至少有时比组合更可取。我想挑战这个假设,希望获得一些理解Java 为什么要使用继承呢?,java,oop,language-agnostic,inheritance,composition,Java,Oop,Language Agnostic,Inheritance,Composition,我知道这个问题一直存在,但似乎总是基于这样的假设,即继承至少有时比组合更可取。我想挑战这个假设,希望获得一些理解 我的问题是:既然你可以用对象组合完成任何你可以用经典继承完成的事情,既然经典继承经常被滥用[1],既然对象组合让你可以灵活地更改委托对象运行时,你为什么要用经典继承? 我可以理解为什么你会推荐一些java语言和C++语言中的继承,这些语言不适合委派方便的语法。在这些语言中,只要不明显不正确,就可以通过使用继承来节省大量的输入。但是像Objective C和Ruby这样的其他语言提供了
我的问题是:既然你可以用对象组合完成任何你可以用经典继承完成的事情,既然经典继承经常被滥用[1],既然对象组合让你可以灵活地更改委托对象运行时,你为什么要用经典继承? <>我可以理解为什么你会推荐一些java语言和C++语言中的继承,这些语言不适合委派方便的语法。在这些语言中,只要不明显不正确,就可以通过使用继承来节省大量的输入。但是像Objective C和Ruby这样的其他语言提供了经典继承和非常方便的委托语法。据我所知,Go编程语言是唯一一种认为经典继承比它的价值更麻烦的语言,它只支持代码重用的委托 陈述我的问题的另一种方式是:即使您知道经典继承对于实现某个模型来说并不是不正确的,但这是否足以作为使用它而不是组合的理由 [1] 许多人使用经典继承来实现多态性,而不是让他们的类实现接口。继承的目的是代码重用,而不是多态性。此外,有些人使用继承来模拟他们对“是一种”关系的直观理解 更新 我只是想澄清一下,当我谈到继承时,我的确切意思是: 我是说。我并不是说从一个纯粹抽象的基类继承,它相当于实现一个接口,我没有反对这个接口 更新2
<>我知道继承是实现多态性C++的唯一途径。在这种情况下,很明显你为什么必须使用它。因此,我的问题仅限于Java或Ruby等语言,它们提供了实现多态性的不同方法(分别是接口和duck类型)。使用继承的主要原因是而不是作为一种组合形式,这样您就可以获得多态行为。如果不需要多态性,则可能不应该使用继承,至少在C++中是这样。
struct Output {
virtual bool readyToWrite() const = 0;
virtual void write(const char *data, size_t len) = 0;
};
struct NetworkOutput : public Output {
NetworkOutput(const char *host, unsigned short port);
bool readyToWrite();
void write(const char *data, size_t len);
};
struct FileOutput : public Output {
FileOutput(const char *fileName);
bool readyToWrite();
void write(const char *data, size_t len);
};
现在想象一下,如果这是Java。”“输出”不是结构,而是“接口”。它可能被称为“可写”。您可以说“implements Writable”,而不是“public Output”。就设计而言有什么不同
无。接口只定义对象可以做什么,而不定义如何做。所以简单地说,接口就是契约。实现接口的所有对象都必须定义自己的契约实现。在实际世界中,这会给您提供
关注点分离
。想象一下,您正在编写一个应用程序,它需要处理各种您事先不知道的对象,但您仍然需要处理它们,您唯一知道的是这些对象应该做什么。因此,您将定义一个接口,并在合同中提及所有操作。现在,您将根据该接口编写应用程序。稍后,无论谁想要利用您的代码或应用程序,都必须在对象上实现接口,使其与您的系统一起工作。您的接口将强制其对象定义契约中定义的每个操作应该如何完成。通过这种方式,任何人都可以编写实现您的接口的对象,以便让它们完美地适应您的系统,您所知道的就是需要做什么,而需要做什么的正是对象
public enum Language
{
English, German, Spanish
}
public class SpeakerFactory
{
public static ISpeaker CreateSpeaker(Language language)
{
switch (language)
{
case Language.English:
return new EnglishSpeaker();
case Language.German:
return new GermanSpeaker();
case Language.Spanish:
return new SpanishSpeaker();
default:
throw new ApplicationException("No speaker can speak such language");
}
}
}
[STAThread]
static void Main()
{
//This is your client code.
ISpeaker speaker = SpeakerFactory.CreateSpeaker(Language.English);
speaker.Speak();
Console.ReadLine();
}
public interface ISpeaker
{
void Speak();
}
public class EnglishSpeaker : ISpeaker
{
public EnglishSpeaker() { }
#region ISpeaker Members
public void Speak()
{
Console.WriteLine("I speak English.");
}
#endregion
}
public class GermanSpeaker : ISpeaker
{
public GermanSpeaker() { }
#region ISpeaker Members
public void Speak()
{
Console.WriteLine("I speak German.");
}
#endregion
}
public class SpanishSpeaker : ISpeaker
{
public SpanishSpeaker() { }
#region ISpeaker Members
public void Speak()
{
Console.WriteLine("I speak Spanish.");
}
#endregion
}