使用Obj-C协议实现类的可插拔性,类似于Java接口

3

背景: 我对研究和创建更好的随机数生成器一直很感兴趣,并将其作为个人实验。此外,我开始学习Objective-C和iOS开发。因此,我认为一个很好的练习项目是将我的随机数生成器想法移植到iOS应用程序中以供娱乐。我在Java方面有相当强的背景,所以我已经做了几次类似于我即将提到的事情,但是我的Objective-C技能还比较新手,所以我不确定如何去做。

意图: 我正在使用UITableVIew提供我想出的生成器列表。再次强调,这是为了尝试我的想法,并练习我的iOS开发技能,但我正在尝试做一些可以使我的未来开发更加清晰和易于操作的事情。我一直试图使用Obj-C协议来实现我的目标,因为根据我的研究和阅读,它们与Java中的接口是相同的。

所以,我想做的是能够定义一个协议(我已经知道如何做),要求任何“实现”该协议的人实现其中的方法(我已经知道如何做),但是能够声明按照协议定义的对象类型,而不是按照特定的随机数类,这样创建和添加新的生成器到列表中就很容易了,因为我不必担心将任何内容与表格链接起来,只需添加符合协议的新生成器类即可。我知道我想要什么,我知道这些词,我只是不确定如何表达。

我已经做了什么:

在Java中,以下方式是可能的、有效的并且常见的:

Bar.java

public interface Bar{

    public void sayHello();

}

Foo.java

public class Foo implements Bar{

    public void sayHello(){
        System.out.println("Hello");
}

Main.java

import com.somepackage.*;//so we can go ahead and pickup everything I've put in there

public class Main{
    public static void main(String[] args){
        Bar bar = new Foo();//usually figure out how I'm going to autoload the class instead of instantiating it manually so as not to break my architecture and pluggability.
        bar.sayHello();
    }
}

以下代码可以在控制台上漂亮地打印出“Hello”。我看到过很多人这样做,我自己也在Java中几次尝试过。

下面是我在Objective-C中尝试的代码:

Bar.h(假设有必要)#import

@protocol Bar : NSObject
    -(NSInteger) generateRandomNumber;
@end

MyConformingViewController.m 假设接口已经声明,且导入已处理

@interface MyConformingViewController() <Bar>
@end
@implmentation MyConformingViewController
    -(NSInteger) generateRandomNumber{
        return 0;
    }
@end

MyTableViewController.m 假设接口已经声明

(该文件)假定接口已经声明。
@interface MyTableViewController
@end

@implementation MyTableViewController

//assume normal methods for a view controller are in place

//only load views into the table view that conform to that protocol

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    Bar *bar = [[MyConformingViewController alloc] init];//build will fail
    //insert proper logic to load the view tapped on based on whether or not it conforms to that protocol
}

@end

问题结束

我正在尝试模拟我在Java中所做的事情。其中大部分我可以自己解决,但是我遇到了一个难以表达的问题。如果需要更多信息或有其他架构建议,请告诉我。我已经查看了关于协议的这个问题,但它没有按照我希望的方式回答我的问题,并且我也阅读了书籍和苹果关于协议的所有文档。我可能只是想太多了,问题可能很简单。

流程:

声明协议

在视图控制器中实现协议

在表视图控制器中,能够创建实现该协议的对象实例

根据用户点击加载所选视图控制器

仅显示实现该协议的类在表视图控制器中


我希望你熟悉密码伪随机数生成器(PRNG),还有/dev/random和arc4random。 - zaph
否则我不会这样做。这主要是为了我的研究和学习。 - Zarathuztra
1个回答

3
我认为你的理解几乎正确,但是:
Bar *bar = [[MyConformingViewController alloc] init];

应该是

id <Bar> bar = [[MyConformingViewController alloc] init];

因为 id <Bar> 声明了一个符合 Bar 协议的 Objective-C 对象。


今天下班后我会确认这是否可行,如果可以,请继续并接受答案。谢谢!非常清晰易懂! - Zarathuztra
Martin,你给出的方法在启用ARC时不起作用,但是将id更改为NSObject确实起作用,或者从bar中删除指针也可以。我记得在某个地方读过id和NSObject实际上并不是相同的东西(我会回去重新阅读我的书来确认),这可能可以解释它。无论如何,在将其更改为NSObject或删除指针符号后,它都可以正常工作。谢谢! - Zarathuztra
@Zarazthuztra:你说得对,id已经是一个指针了,那是我的错误,我会在答案中修正它。无论如何,我很高兴它能帮到你。 - Martin R
放心吧,伙计,如果 Xcode 没有警告我,我也不会注意到那个问题 :) - Zarathuztra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接