草庐IT

iphone - objective-c 的奇怪行为

coder 2024-01-11 原文

实际上我来自 java 背景,我正在学习 objective-c 。我对 Objective-C 的奇怪行为感到非常困惑。“请阅读第 3 个问题,它很重要。”

问题是按顺序提供的,所以请按我和其他人都能理解的顺序给出答案。

问题一
我有两个派生自 NSObject 的类: AB :

@interface A : NSObject 
@end                               

@interface B : NSobject
-(void)display; // It displays "I am class B"
@end

现在如果我这样做:

A *a = [[B alloc]init]; // Show warning not error (it must be illegal)
[a display];            // prints "I am class B"

它调用了类 B 的显示方法。我认为它不应该发生,因为:

  1. A没有方法 display .通过多态性。

  2. 这可能是一种安全威胁,因为我正在创建任何类的引用并传递任何其他类的对象并通过它访问数据。

  3. 可能存在设计问题 Dog类实例获取 Printer 的对象上课,现在我调用print Dog 上的方法实例。

  4. 我引用了 NSArray并传递了 NSMutableArray 的对象现在我调用NSMutableArray此实例上的方法。

    [nsarr addObject:@:abc];//看起来很奇怪

问题二
如果我有 Foo协议(protocol),如果有任何类没有确认它。不应允许在协议(protocol)引用中获取该类的对象。

@protocol Foo
@required
-(void)abc;
@end    

如果我调用:

id<Foo> obj= [[B alloc]init]; // Shows warning ignore it for now as it must be illegal also
[obj display];                // It will call display method which should be illegal  
  1. 这不应该发生,因为B不符合协议(protocol)Fooobj正在服用 B对象和调用 B实例方法。我认为它非常糟糕,因为多态性和安全性

问题三
如果我的类有一个类方法返回该类的一个未自动释放的对象,则编译器会显示警告。如果我将该类(不符合协议(protocol))方法返回的对象传递给协议(protocol)的引用。 (它应该是一个错误)。

id<Foo> obj = [Abc aClassMethodReturnsObjectWhichNotAutoreleased]; //show warning

它显示了一个很好的警告。 Abc不符合协议(protocol)Foo

但是

id<Foo> obj = [NSArray arrayWithObjects:@"abc",@"def",nil]; // It does **not** show a warning as it will return autorelease object. NSArray doesn't conform protocol Foo

为什么上面的赋值给了NSArray类不显示警告,因为它在前面的示例中显示。

提前致谢。

编辑

*回答第三个问题:*由于 NSArray 返回允许传入“id obj”的 id 对象,但在“aClassMethodReturnsObjectWhichNotAutoreleased”的情况下,该方法返回“ABC *”指针,这就是编译器的原因在这种情况下发出警告。

最佳答案

问题一:

A *a = [[B alloc]init]; //Show warning not error (it must be illegal)
[a display];  //prints "I am class B"

在这里,您为名为 a 的变量使用静态类型 A。然后,您将另一种类型的对象 (B) 分配给该变量。

与 java 不同,Objective-C 不会强制静态类型要求,但是它会在编译时警告您,因为编译器检测到声明的类型之间存在差异类型和对象的实际类型。不过,它很乐意将 B 对象填充到您的变量中,因此 a 现在指向您创建的 B 对象。一旦程序编译并运行(在运行时),A *a 将被视为与 id a 相同。

Objective-C 的另一个特性是您可以随时向任何对象发送任何消息。这是 Objective-C 动态特性的一部分。显然,在某些情况下,向对象发送错误消息会导致坏事 (tm) 发生,因此您需要确保只发送适当的消息。有多种函数可以在运行时测试对象的类,甚至可以在发送消息之前测试它是否能够处理特定消息,以防止坏事。如果您使用的是静态类型(如本例所示),那么编译器会发出警告,告诉您您可能犯了错误,应该检查代码。

问题 2:

这实际上与问题 1 非常相似。编译器警告您,您正在为变量分配看似不正确的值,但是在运行时您可以向任何对象发送任何消息,因此它会起作用在实际对象上,而不是类型声明中的“预期”对象。

问题 3:

好问题。我原以为你也会在那里收到警告。也许其他人可以提供帮助。我的第一个想法是这是一个错误,应该这样报告,但可能有一个我不知道的原因....

关于iphone - objective-c 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13322974/

有关iphone - objective-c 的奇怪行为的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  3. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  4. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  5. ruby - Ruby gsub 替换中的行为不一致? - 2

    两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

  6. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

  7. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  8. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

    假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

  9. ruby - 你会如何在 Ruby 中表达成语 "with this object, if it exists, do this"? - 2

    在Ruby(尤其是Rails)中,您经常需要检查某物是否存在,然后对其执行操作,例如:if@objects.any?puts"Wehavetheseobjects:"@objects.each{|o|puts"hello:#{o}"end这是最短的,一切都很好,但是如果你有@objects.some_association.something.hit_database.process而不是@objects呢?我将不得不在if表达式中重复两次,如果我不知道实现细节并且方法调用很昂贵怎么办?显而易见的选择是创建一个变量,然后测试它,然后处理它,但是你必须想出一个变量名(呃),它也会在内存中

  10. ruby - 了解在 Ruby 中与 lambda 一起使用的 inject 行为 - 2

    我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject

随机推荐