可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Guys before you start down voting me please read this question and please understand that I do not try to start anything unpleasant here.
The only reason for this question is that I'm becoming more and more aware of that in order to be more employable I have to know either Java and/or C#.
Ok here is the question:
I know that multiple inheritance is forbidden in J and C#. But if I do something like this (because I would like to have a class which inherits from two classes B and A):
//code in Java
public class B
{
public void methodFromB()
{
}
}
public class A extends B
{
public void methodFromA()
{
}
}
public class C extends A
{
public void methodFromC()
{
}
}
So in fact as far as I understand this, I do inherit from both of them (A and B and yes I do understand that formal explanation for this is that the object A is a specialized B but none the less if I want to do it I will but it just doesn't look pretty)
But instead of doing this in one declaration I have to first create one class inherit from another class and then derive from it?
Funny thing though. Having declared those classes as above (in NetBeans) I see that after creating an instance of class C (in main) I cannot invoke methodFromC on it which is the method defined in this class.
What is the reason for that?
Thanks.
回答1:
Your definition of multiple inheritance is not correct.
At the OO level, multiple inheritance is well and clearly defined.
And both C++ and Java support multiple inheritance.
The problem is that most programmers have absolutely zero OO/OOA/OOD notions and all they know are OOP implementation details. Hence their wrong belief that "inheritance" is synonym to "implementation inheritance".
However this is completely wrong.
Because Java support multiple (interface) inheritance, which happens to be the real and only form of inheritance that exists at the Object-Oriented-Analysis / Object-Oriented-Design level.
Show me any OOD resulting from an OOA and that is using multiple inheritance and I can translate it cleanly to OOP in Java using multiple interface inheritance (as an added bonus in Java the "diamond" problem doesn't exist).
回答2:
Even though you are creating an instance of C
, whether C's methods are visible depends upon the compile-time type that you are using. For example,
C c = new C();
c.methodFromC(); // fine
Is valid, but
A a = new C();
a.methodFromC(); // compiler error
is not, since the compile time type is an A
, which does not have methodFromC
declared.
Note that since both C and A are subclasses of B, calling methodFromB
would be fine in both cases.
回答3:
I agree with mdma. Also note that this is NOT multiple inheritance, this is chained inheritance. Multiple inheritance is when a class inherits from more than one class at the same time:
class A {}
class B {}
class C extends A, B {}
Which is forbidden if you're not coding in C++
回答4:
That is not multiple inheritance. And you are right C# does not support true multiple inheritance. For what it is worth the canonical pattern for simulating multiple inheritance in C# is below.
public interface IA
{
void DoA();
}
public interface IB
{
void DoB();
}
public class A : IA
{
public void DoA() { Console.WriteLine("A"); }
}
public class B : IB
{
public void DoB() { Console.WriteLine("B"); }
}
public class MultipleInheritanceExample : IA, IB
{
private IA m_A = new A();
private IB m_B = new B();
public void DoA() { m_A.DoA(); }
public void DoB() { m_B.DoB(); }
}
It is definitely not as elegant as pure mulitple inheritance, but gets the job done, albiet with more work. You get most of the benefits of multiple inheritance including the most important one, polymorphism. However, you do not inherit the implementation. You have to reimplement all members inherited from all base classes. This is done by mapping those member calls onto concrete instances of each base class.
In C# you can take advantage of extension methods to mitigate the problem of not inheriting the implementation.
public static class IAExtensions
{
public static void Foo(this IA target)
{
target.DoA();
}
}
This, of course, has its own problems. It is not actually causing any kind of inheritance which means the IA
interface does not actually have the Foo
method. That means only the code which imports the IAExtensions
class can use methods from it. In other words, there is no polymorphism here.
You can use of these mechanisms together to cludge together something, that for the most part, resembles and functions like multiple inheritance, but it is not as elegant. Personally, I find the workarounds that C# developers are adopting to mimic mulitple inheritance more offensive than if pure multiple inheritance were used. But, it is unlikely that C# will get mulitple inheritance any time soon or perhaps ever.
回答5:
An alternative in C# (and may exist in Java, but I'm not a Java person so I don't know) is interfaces.
public interface C
{
int SomeMethodInC();
}
public class A
{
}
public class B : A, C
{
}
... in other class....
B someB = new B();
i someInt = someB.SomeMethodInC();
It looks like multiple inheritance, but it isn't. Interface C defines the signature for someMethodInC, but not the implementation. Class B will have to implement someMethodInC.
In C#, you can inherit from only one class, but you can inherit multiple interfaces. (Same in Java, I think.)
In C#, you can also attach implementations to interfaces by using extension methods.
public static class CExtensions
{
public static int SomeExtensionToC(this C someC, int someInt)
{
return someInt * 2;
}
}
... in code ...
B objB = new B();
y = objB.SomeExtensionToC(x);
Both the method and implemention of SomeExtensionToC will be available to any class that inherits interface C
. Note that both the class and method are static, and that the first parameter includes the keyword "this" in reference to an object implementing C. Some parts of the .NET framework (LINQ, as an example) are implemented as extension methods to IEnumerable<T>
.
Almost like multiple inheritance, without the bad parts. And the extension methods are still considered part of the interface, so can be considered as part of the "contract" inherent in interface C.