我是Python的新手......并且来自大多数Java背景,如果它可以解释任何问题.
我正在尝试理解Python中的多态性.也许问题是我期待我已经知道的概念投射到Python中.但我把以下测试代码放在一起:
class animal(object):
"empty animal class"
class dog(animal):
"empty dog class"
myDog = dog()
print myDog.__class__ is animal
print myDog.__class__ is dog
Run Code Online (Sandbox Code Playgroud)
从我习惯的多态性(例如java的instanceof),我希望这两个语句都打印为true,因为dog的一个例子是动物,也是一只狗.但我的输出是:
False
True
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
任何人都可以请给我一个现实生活,多态的实例吗?我的教授告诉我我一直听到的关于+操作员的老故事.a+b = c而且2+2 = 4,这是多态性.我真的无法将自己与这样的定义联系起来,因为我已经在很多书中阅读并重读了这个定义.
我需要的是一个带代码的真实世界示例,我可以真正地与之相关联.
例如,这是一个小例子,以防你想扩展它.
>>> class Person(object):
def __init__(self, name):
self.name = name
>>> class Student(Person):
def __init__(self, name, age):
super(Student, self).__init__(name)
self.age = age
Run Code Online (Sandbox Code Playgroud) 我有一个基类,其中包含一个属性(get方法),我想在子类中覆盖它.我的第一个想法是:
class Foo(object):
def _get_age(self):
return 11
age = property(_get_age)
class Bar(Foo):
def _get_age(self):
return 44
Run Code Online (Sandbox Code Playgroud)
这不起作用(子类bar.age返回11).我发现了一个带有lambda表达式的解决方案:
age = property(lambda self: self._get_age())
Run Code Online (Sandbox Code Playgroud)
那么这是使用属性并在子类中覆盖它们的正确解决方案,还是有其他首选方法来执行此操作?
作为ASP.NET MVC的新手,我一直想知道Controller方法的签名.在我看过的所有示例中,它们似乎总是返回ActionResult,即使它们实际返回ViewResult实例或类似实例.
这是一个常见的例子:
public ActionResult Index()
{
return this.View();
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,将方法声明为public ViewResult Index()并获得更强的类型支持是不是更有意义?
实验表明这是有效的,所以似乎有可能.
我确实意识到可能存在需要多态的情况(例如,如果你只想在某些情况下重定向,但在其他情况下显示视图),但如果方法总是返回一个视图,我会发现更多的ViewResult可取的.
就未来的兼容性而言,ActionResult显然提供了更强大的签名,但如果有人控制整个代码库,则总是可以将方法的签名更改为更通用的返回类型(如果将来需要它).
是否有其他我不了解的注意事项,或者我应该继续并使用特定的返回类型声明我的控制器方法?
之前在早期版本的MVC中已经提出过这个问题.还有一篇关于解决问题的方法的博客文章.我想知道MVC3是否引入了任何可能有用的东西,或者是否还有其他选择.
简而言之.这是情况.我有一个抽象的基本模型和2个具体的子类.我有一个强类型视图,用于渲染模型EditorForModel().然后我有自定义模板来呈现每个具体类型.
问题来自发布时间.如果我使post post方法取基类作为参数,那么MVC不能创建它的抽象版本(我不想要它,我希望它创建实际的具体类型).如果我创建多个仅通过参数签名变化的后期操作方法,那么MVC会抱怨它不明确.
据我所知,我对如何解决这个问题有一些选择.我出于各种原因不喜欢它们,但我会在这里列出它们:
我不喜欢1,因为它基本上是隐藏的配置.其他一些开发代码的开发人员可能不知道它并浪费了大量时间来弄清楚为什么在更改内容时会出现问题.
我不喜欢2,因为它似乎有点hacky.但是,我倾向于这种方法.
我不喜欢3,因为这意味着违反DRY.
还有其他建议吗?
编辑:
我决定采用达林的方法,但稍作改动.我把它添加到我的抽象模型中:
[HiddenInput(DisplayValue = false)]
public string ConcreteModelType { get { return this.GetType().ToString(); }}
Run Code Online (Sandbox Code Playgroud)
然后隐藏自动生成我的DisplayForModel().你唯一需要记住的是,如果你不使用DisplayForModel(),你必须自己添加它.
我确实在SO上发现了一些类似标题的问题 - 但是当我读到答案时,他们关注的是问题的不同部分,这些部分是非常具体的(例如STL /容器).
有人可以告诉我为什么你必须使用指针/引用来实现多态?我可以理解指针可能会有所帮助 - 但肯定只能引用区分传值和传递参考?
当然,只要你在堆上分配内存 - 这样你就可以拥有动态绑定,那么这就足够了 - 显然不是.
请考虑以下示例:
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void makeSound() {cout << "rawr" << endl;}
};
class Dog : public Animal
{
public:
virtual void makeSound() {cout << "bark" << endl;}
};
int main()
{
Animal animal;
animal.makeSound();
Dog dog;
dog.makeSound();
Animal badDog = Dog();
badDog.makeSound();
Animal* goodDog = new Dog();
goodDog->makeSound();
}
Run Code Online (Sandbox Code Playgroud)
输出是:
rawr
bark
rawr
bark
Run Code Online (Sandbox Code Playgroud)
但我认为产量肯定应该是"粗树皮树皮".badDog有什么用?
更新:您可能对我的另一个问题感兴趣.
我想在向量中存储几个类的实例.由于所有类都继承自相同的基类,因此这是可能的.
想象一下这个程序:
#include <iostream>
#include <vector>
using namespace std;
class Base
{
public:
virtual void identify ()
{
cout << "BASE" << endl;
}
};
class Derived: public Base
{
public:
virtual void identify ()
{
cout << "DERIVED" << endl;
}
};
int main ()
{
Derived derived;
vector<Base> vect;
vect.push_back(derived);
vect[0].identify();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望它能打印"DERIVED",因为"识别"方法是虚拟的.相反,'vect [0]'似乎是一个'Base'实例,它打印出来
基础
我想我可以写一个我自己的容器(可能是从vector派生的),不知何故能够做到这一点(也许只能拿指针......).我只是想问一下是否有更多的C++ ish方法来做到这一点.我希望完全兼容矢量(只是为了方便其他用户应该使用我的代码).
我想了解参数多态性之间的关键区别,例如Java/Scala/C++语言中泛型类/函数的多态性和Haskell类型系统中的"ad-hoc"多态性.我熟悉第一种语言,但我从未使用过Haskell.
更确切地说:
提前致谢.
这些有什么区别?我想我理解存在类型是如何工作的,它们就像在OO中拥有一个基类而没有一种方法可以用.普遍类型有何不同?
polymorphism ×10
c++ ×3
python ×3
asp.net-mvc ×2
haskell ×2
actionresult ×1
inheritance ×1
java ×1
oop ×1
pointers ×1
properties ×1
types ×1
viewresult ×1
virtual ×1