我仍然是Objective-C的新手,我想知道以下两个语句之间有什么区别?
[object performSelector:@selector(doSomething)];
[object doSomething];
Run Code Online (Sandbox Code Playgroud) 在集成我之前没有使用的Django应用程序时,我发现了两种不同的方法来定义类中的函数.作者似乎非常故意地使用它们.第一个是我自己经常使用的一个:
class Dummy(object):
def some_function(self,*args,**kwargs):
do something here
self is the class instance
Run Code Online (Sandbox Code Playgroud)
另一个是我不使用的,主要是因为我不明白何时使用它,以及为什么:
class Dummy(object):
@classmethod
def some_function(cls,*args,**kwargs):
do something here
cls refers to what?
Run Code Online (Sandbox Code Playgroud)
在Python文档中,classmethod装饰器用这句话解释:
类方法接收类作为隐式的第一个参数,就像实例方法接收实例一样.
所以我猜cls是指Dummy自己(class不是实例).我不完全理解为什么会这样,因为我总能做到这一点:
type(self).do_something_with_the_class
Run Code Online (Sandbox Code Playgroud)
这只是为了清楚起见,还是我错过了最重要的部分:如果没有它,那些怪异而迷人的东西是无法完成的?
python language-details method-dispatch class-method language-lawyer
我知道覆盖和重载之间的语法差异.而且我也知道overriding是运行时多态,而重载是编译时多态.但我的问题是:"重载是真的编译时多态吗?方法调用是否真的在编译时解决?".为了澄清我的观点,让我们考虑一个示例类.
public class Greeter {
public void greetMe() {
System.out.println("Hello");
}
public void greetMe(String name) {
System.out.println("Hello " + name);
}
public void wishLuck() {
System.out.println("Good Luck");
}
}
Run Code Online (Sandbox Code Playgroud)
由于所有方法greetMe(), greetMe(String name), wishLuck()都是公开的,所以它们都可以被覆盖(包括重载的方法),对吧?例如,
public class FancyGreeter extends Greeter {
public void greetMe() {
System.out.println("***********");
System.out.println("* Hello *");
System.out.println("***********");
}
}
Run Code Online (Sandbox Code Playgroud)
现在,请考虑以下代码段:
Greeter greeter = GreeterFactory.getRandomGreeter();
greeter.greetMe();
Run Code Online (Sandbox Code Playgroud)
该getRandomGreeter()方法返回一个随机Greeter对象.它可以返回其对象Greeter或其任何子类,如FancyGreeter或GraphicalGreeter或任何其他子类.在getRandomGreeter()将或者使用创建的对象new或动态地加载类文件,并使用反射(我认为这是可能的反射)或这是可能的任何其他方式创建对象.所有这些方法都Greeter可以在子类中重写或不重写.因此编译器无法知道是否覆盖了特定方法(是否重载).对?此外,维基百科在虚拟功能上说:
在Java中,所有非静态方法默认为"虚函数".只有标记为关键字final的方法(不能被覆盖)以及未被继承的私有方法才是非虚拟方法.
因为,使用动态方法分派在运行时解析虚函数,并且由于所有非私有,非最终方法都是虚拟的(无论是否过载),因此必须在运行时解析它们.对?
那么,如何在编译时仍然可以解决重载?或者,有什么我误解了,或者我错过了什么?
为什么它(显然)有所作为是否我通过null直接作为参数,或者传递一个Object,我分配的价值 null?
Object testVal = null;
test.foo(testVal); // dispatched to foo(Object)
// test.foo(null); // compilation problem -> "The method foo(String) is ambiguous"
public void foo(String arg) { // More-specific
System.out.println("foo(String)");
}
public void foo(Object arg) { // Generic
System.out.println("foo(Object)");
}
Run Code Online (Sandbox Code Playgroud)
换句话说,为什么第二次调用(已注释掉)foo(...)未调度到foo(Object)?
更新:我使用Java 1.6.我可以毫无问题地编译Hemal的代码,但我仍然无法编译.我看到的唯一区别是,Hemal的方法是静态的,而我的方法则不是.但我真的不明白为什么这应该有所作为......?
更新2:解决了.我的班级中有另一个方法foo(Runnable),因此调度员无法明确地选择最具体的方法.(请参阅我在Hemal的第二个答案中的评论.)感谢大家的帮助.
protocol A {
func f()
}
struct S1 : A {
func f() {
print("S1")
}
}
struct S2 : A {
func f() {
print("S2")
}
}
let array: [A] = [S1(), S2()]
for s: A in array {
s.f()
}
// "S1\n" "S2\n"
Run Code Online (Sandbox Code Playgroud)
如果这是一个继承层次结构,我希望 Swift 使用 v-table 来查找正确的实现。然而, in 的具体类型array可以是任何实现 的东西A,以及任意数量的其他协议,那么如果 Swift 运行时也使用 v-tables,它如何知道对象的结构?
我正在开发一个Ruby应用程序,我在其中动态调用基于JSON数据的方法.松散:
def items
# do something
end
def createItem( name:, data:nil )
# do something that requires a name keyword argument
end
def receive_json(json) # e.g. { "cmd":"createItem", "name":"jim" }
hash = JSON.parse(json)
cmd = hash.delete('cmd')
if respond_to?(cmd)
params = Hash[ hash.map{ |k,v| [k.to_sym, v } ]
method(cmd).arity==0 ? send(cmd) : send(cmd,params)
end
end
Run Code Online (Sandbox Code Playgroud)
如上所示,某些方法不带参数,有些方法带有关键字参数.在Ruby 2.1.0(我正在开发)中arity,上述两种方法都是0.但是,如果我send(cmd,params)总是这样,那么对于不带参数的方法我会收到错误.
如何send在需要时使用正确传递关键字参数,但在没有时省略它们?
我正在努力从我的应用程序中榨取最后一点性能。我尝试尽可能使用结构而不是类(无状态共享、默认直接调度等)。但我的视图控制器和 UIView 对象显然仍然是类。出于性能原因,我想强制直接调度我的每一个方法和数据成员。
\n\n我是否仍然需要在类中标记每个var、let和func为Final,还是只需将托管类标记为 Final 就足够了,以便其下面的所有内容都可以利用直接方法分派?
\n\n换句话说:在每个方法和变量之前粘贴 Final 是非常乏味的。所以我希望将它放在类本身上具有强制直接调度所有类成员的相同效果。但我不知道如何测试或验证它。
\n\n对于那些想知道我在说什么的人,请查看这篇文章:“Swift 中的方法调度”。默认情况下,结构和协议扩展为您提供静态方法分派(性能最快),但类则不然。类中的静态方法可以,但我想对所有实例方法和数据成员强制静态调度。
\n https://www.raizlabs.com/dev/2016/12/swift-method-dispatch/
swift 语言运行时文档提到了对子类化能力的影响,但没有描述标记为“final”的类的子成员和函数的分派行为会发生什么。如果下面的所有内容都获得静态方法调度而不必单独将所有内容标记为最终版本,那就太好了。
\n\n\n\n最终的
\n\n将此修饰符应用于类或类的属性、方法或下标成员。它应用于一个类以指示该类不能被子类化。它应用于类的属性、方法或下标,以指示类成员不能在任何子类中被覆盖。有关如何使用 Final 属性的示例,请参阅防止覆盖。
\n
我试图了解如何找到协议方法的实现。
我知道 Swift 使用存在容器在堆栈内存中进行固定大小的存储,它管理如何描述内存中的实例struct。它有一个值见证表(VWT)和协议见证表(PWT)
VWT 知道如何管理结构实例中的实际值(它们的生命周期),PWT 知道协议方法的实现。
但我想知道结构体实例和“存在容器”之间的关系。
的实例是否struct有一个指向存在容器的指针?
a 的实例如何struct知道它的存在容器?
我正在练习考试,发现了一个让我完全迷失的样本问题.对于以下代码,找到输出的内容:
class Moe {
public void print(Moe p) {
System.out.println("Moe 1\n");
}
}
class Larry extends Moe {
public void print(Moe p) {
System.out.println("Larry 1\n");
}
public void print(Larry l) {
System.out.println("Larry 2\n");
}
}
class Curly extends Larry {
public void print(Moe p) {
System.out.println("Curly 1\n");
}
public void print(Larry l) {
System.out.println("Curly 2\n");
}
public void print(Curly b) {
System.out.println("Curly 3\n");
}
}
public class Overloading_Final_Exam {
public static void main (String [] args) {
Larry stooge1 = …Run Code Online (Sandbox Code Playgroud) 考虑这个人为的例子:
# Dispatch on value of fruit_kind:
TYPE_A = :apple
TYPE_B = :banana
TYPE_C = :cherry
eating_method = nil
case fruit_kind
# Methods to use for different kinds of fruit (assume these are
# already defined)
when TYPE_A then eating_method = bite
when TYPE_B then eating_method = peel
when TYPE_C then eating_method = om_nom_nom
end
Run Code Online (Sandbox Code Playgroud)
现在我想eating_method用一些参数来调用目标:
# Doesn't work; this tries to invoke a method called "eating_method",
# not the reference I defined earlier.
eating_method(some_fruit)
Run Code Online (Sandbox Code Playgroud)
在Ruby中这样做的正确方法是什么?
method-dispatch ×10
java ×3
swift ×3
overloading ×2
polymorphism ×2
ruby ×2
binding ×1
class-method ×1
dispatch ×1
final ×1
idioms ×1
null ×1
objective-c ×1
overriding ×1
performance ×1
python ×1
selector ×1