我正在运行Python 2.5,因此这个问题可能不适用于Python 3.当您使用多重继承创建钻石类层次结构并创建派生最多类的对象时,Python会执行Right Thing(TM).它调用派生最多类的构造函数,然后调用从左到右列出的父类,然后是祖父母.我熟悉Python的MRO ; 那不是我的问题.我很好奇从super返回的对象实际上如何管理与父类中的super调用正确的顺序进行通信.考虑这个示例代码:
#!/usr/bin/python
class A(object):
def __init__(self): print "A init"
class B(A):
def __init__(self):
print "B init"
super(B, self).__init__()
class C(A):
def __init__(self):
print "C init"
super(C, self).__init__()
class D(B, C):
def __init__(self):
print "D init"
super(D, self).__init__()
x = D()
Run Code Online (Sandbox Code Playgroud)
代码做直观的事情,它打印:
D init
B init
C init
A init
Run Code Online (Sandbox Code Playgroud)
但是,如果你在B的init函数中注释掉对super的调用,则不会调用A和C的init函数.这意味着B对super的调用在某种程度上意识到C在整个类层次结构中的存在.我知道super返回一个带有重载get运算符的代理对象,但是在D的init定义中super返回的对象如何将C的存在传达给B的init定义中super返回的对象?后续超级使用调用的信息是否存储在对象本身上?如果是这样,为什么不是超级而不是self.super?
编辑:Jekke非常正确地指出它不是self.super,因为super是类的属性,而不是类的实例.从概念上讲,这是有道理的,但在实践中,超级也不是班级的属性!您可以在解释器中通过创建两个类A和B来测试它,其中B继承自A,并且调用dir(B).它没有super或__super__属性.
下面的代码片段在编译过程中会产生一个"foo的foo调用"错误,我想知道如果没有完全限定对foo的调用,是否有任何方法解决这个问题:
#include <iostream>
struct Base1{
void foo(int){
}
};
struct Base2{
void foo(float){
}
};
struct Derived : public Base1, public Base2{
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以,问题就像标题所说的那样.想法?我的意思是,以下工作完美无瑕:
#include <iostream>
struct Base{
void foo(int){
}
};
struct Derived : public Base{
void foo(float){
}
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
Run Code Online (Sandbox Code Playgroud) 在C#编程语言中, Krzysztof Cwalina在一个注释中说:
我们明确决定不添加对多重继承的支持[...]缺少多重继承迫使我们添加接口的概念,这反过来又导致了框架演化,更深层次的继承层次结构等问题.问题.
接口是OO编程语言的核心概念.我不遵循"强迫我们添加接口的概念"的含义
Krzysztof是否意味着必须就接口的使用做出某些设计决策,否则将使用多重继承?或者,他interface是否因为缺乏多重继承而被引入C#?你能提供一个例子吗?
我想知道某个类的C#扩展方法是否可以作为接口的实现?我有什么:
一个表面:
public interface IEventHandler
{
void Notify(SEvent ev, IEventEmmiter source);
}
Run Code Online (Sandbox Code Playgroud)
实现它的类:
class Sim : IEventHandler
{
/*public void Notify(SEvent ev, IEventEmmiter source)
{
Console.WriteLine("Got notified: " + ev.Name);
}*/
}
Run Code Online (Sandbox Code Playgroud)
还有一个包含扩展方法的类:
public static class ReflectiveEventDispatcher
{
public static void Notify(this IEventHandler handler, SEvent ev)
{
if (handler.GetType().GetMethod("Handle" + ev.Name) != null)
{
// C# WTF?
object[] prms = new object[0];
prms[0] = ev;
handler.GetType().GetMethod("Handle" + ev.Name).Invoke(handler, prms);
}
else
{
throw new System.NotImplementedException("This object doesn't have appropriate handler …Run Code Online (Sandbox Code Playgroud) 在Python中,如何选择要调用哪个Parent方法?假设我想调用父ASDF2的__init__方法.好像我必须在super()中指定ASDF1 ..?如果我想调用ASDF3 __init__,那么我必须指定ASDF2?
>>> class ASDF(ASDF1, ASDF2, ASDF3):
def __init__(self):
super(ASDF1, self).__init__()
>>> ASDF()
ASDF2's __init__ happened
>>> class ASDF(ASDF1, ASDF2, ASDF3):
def __init__(self):
super(ASDF2, self).__init__()
>>> ASDF()
ASDF3's __init__ happened
Run Code Online (Sandbox Code Playgroud)
对我来说似乎疯了.我究竟做错了什么?
我有三个类:A,B和C.
C继承自A和B(按此顺序).构造函数的签名A和B不同.如何调用__init__两个父类的方法?
我在代码中的努力:
class A(object):
def __init__(self, a, b):
super(A, self).__init__()
print('Init {} with arguments {}'.format(self.__class__.__name__, (a, b)))
class B(object):
def __init__(self, q):
super(B, self).__init__()
print('Init {} with arguments {}'.format(self.__class__.__name__, (q)))
class C(A, B):
def __init__(self):
super(A, self).__init__(1, 2)
super(B, self).__init__(3)
c = C()
Run Code Online (Sandbox Code Playgroud)
产生错误:
Traceback (most recent call last):
File "test.py", line 16, in <module>
c = C()
File "test.py", line 13, …Run Code Online (Sandbox Code Playgroud) 经常声明在Python 2 中super应该避免使用.我super在Python 2中使用它发现它永远不会按照我的预期行事,除非我提供所有参数,例如:
super(ThisClass, self).some_func(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
在我看来,这违背了使用的目的super(),它既不简洁,也不比它更好TheBaseClass.some_func(self, *args, **kwargs).在大多数情况下,方法解析顺序是一个遥远的童话故事.
super要继续使用?考虑下面的python代码片段
class A(object):
def __init__(self, a):
self.a = a
class B(A):
def __init__(self, a, b):
super(B, self).__init__(a)
self.b = b
class C(A):
def __init__(self, a, c):
super(C, self).__init__(a)
self.c = c
class D(B, C):
def __init__(self, a, b, c, d):
#super(D,self).__init__(a, b, c) ???
self.d = d
Run Code Online (Sandbox Code Playgroud)
我想知道如何传递a,b以及c相应的基类的构造函数.
谢谢,
我有一个与C++中的多继承相关的基本问题.如果我有如下所示的代码:
struct base1 {
void start() { cout << "Inside base1"; }
};
struct base2 {
void start() { cout << "Inside base2"; }
};
struct derived : base1, base2 { };
int main() {
derived a;
a.start();
}
Run Code Online (Sandbox Code Playgroud)
这给出了以下编译错误:
1>c:\mytest.cpp(41): error C2385: ambiguous access of 'start'
1> could be the 'start' in base 'base1'
1> or could be the 'start' in base 'base2'
Run Code Online (Sandbox Code Playgroud)
有没有办法能够start()使用派生类对象从特定基类调用函数?
我现在不知道用例但是..仍然!
看起来我偶然发现了一个地狱级的地狱,即使我不想和它有任何关系.
我正在使用PySide在Qt4中编写应用程序.我想将事件驱动的部分与从Qt Designer文件生成的UI定义分开.因此,我创建了一个"控制器"类,但为了缓解我的生活,无论如何我多次继承它们.一个例子:
class BaseController(QObject):
def setupEvents(self, parent):
self.window = parent
class MainController(BaseController):
pass
class MainWindow(QMainWindow, Ui_MainWindow, MainController):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.setupEvents(self)
Run Code Online (Sandbox Code Playgroud)
这按预期工作.它也有继承自(QDialog,Ui_Dialog,BaseController).但是当我BaseController继承并尝试从所述子类继承(代替BaseController)时,我收到一个错误:
TypeError:调用元类基类元类冲突时出错:派生类的元类必须是其所有基类的元类的(非严格)子类
澄清:这两个QMainWindow和QDialog继承QObject.BaseController由于Qt事件系统的特殊性,它也必须继承它.Ui_类只继承自简单的Python对象类.我搜索了解决方案,但所有这些都涉及故意使用元类的情况.所以我必须做一些非常错误的事情.
编辑:添加图表可能会更清楚我的描述.
工作范例:
QObject
| \___________________
| object |
QMainWindow | BaseController
| /---Ui_MainWindow |
| | MainController
MainWindow-----------------/
Run Code Online (Sandbox Code Playgroud)
另一个工作示例:
QObject
| \___________________
| object |
QDialog | BaseController
| /---Ui_OtherWindow |
| | | …Run Code Online (Sandbox Code Playgroud) python ×6
super ×4
c# ×2
c++ ×2
interface ×2
oop ×2
python-3.x ×2
constructor ×1
inheritance ×1
metaclass ×1
overloading ×1
python-2.5 ×1
python-2.x ×1
qt4 ×1
scope ×1