如果一个父类(A)和它的子类(A1)都是抽象的(有需要继承他们的子类实现的方法或者设置的属性). 这时应该如何设计接口使得使用子类(A1)的人知道: 不仅需要实现子类中的方法, 还要实现父类中的方法?

2014-01-10 10:30:16 +08:00
 thedevil5032
--- 两个父子关系的抽象类

比如, 我有一个 XXXViewController 以及一个 EditableXXXViewController. 显然 XXXViewController 为 EditableXXXViewController 的父类. XXXViewController 只能显示数据, 但是 EditableXXXViewController 在其父类的基础上除了显示, 还可以编辑数据, 例如添加, 删除等.

当继承 XXXViewController 时, 必须实现的方法有 configureXXX.
而 EditableXXXViewController 必须实现的方法有 configureNewXXX, 以及其父类的 configureXXX.

--- 我想到的解决办法(A, B 为不同方法)

A. 每个类需要其子类实现的 **所有** 方法以及属性放入一个 Protocol, 类本身遵循这个 Protocol, 并且提供这些方法的空实现.
B. 将这些需要实现的方法和属性放入一个 Delegate 中, 同上, Delegate 用一个 Protocol 阐明 **所有** 方法和属性.

* 所有: 也就是说, 子类的 Protocol 实际上并不继承父类的 Protocol, 但 Protocol 包含父类需要实现的方法. (或许这不是一个好的解决方案)

--- TL;DR

困扰我的就是如何能让用 EditableXXXViewController 的人不用走弯路就知道需要实现它的父类方法?

----
初学 Objective-C, 还不是太了解 Objective-C 的设计方法. 所以这个问题或许不是接口设计的问题, 也可能是本身两个类设计的问题.

各位有任何建议都可以提出来, 谢谢. 回复必谢. :D
4849 次点击
所在节点    iDev
11 条回复
dnnta
2014-01-10 11:53:29 +08:00
可以这样试一下
父类中
- configureXXX {
[NSException raise:NSInternalInconsistencyException
format:@“在%@子类中必须重载%@方法”, [NSString stringWithUTF8String:object_getClassName(self)], NSStringFromSelector(_cmd)];
}
如果子类调用时没有重写父类configureXXX 肯定会抛异常了
fangzhzh
2014-01-10 11:58:39 +08:00
我感觉 XXXViewController,EditableXXXViewController 这个类关系可以定义为
类XXXViewController, 和接口 editable, 然后XXXViewController 实现接口. 子类继承XXXViewController时, 可能就必须要关心editable的接口了.
PrideChung
2014-01-10 12:32:16 +08:00
@fangzhzh 既然你两个类都是抽象的,本身一个方法都不实现,还不如弄成两个protocol,XXXing,XXXEditing,然后让UIViewController的子类去实现它们。
railgun
2014-01-10 12:32:53 +08:00
我的理解,楼主所说的抽象类在ObjC里面的实现就是协议
两个协议,协议方法都是@request ,继承关系,应该能满足楼主的需求
fangzhzh
2014-01-10 12:36:51 +08:00
@PrideChung 因为不了解XXXing是什么, 所以没有那么去想.
如果是个动作的话, 并且和Editable是正交的概念, 那么两个protocol也是是更好的方案.
thedevil5032
2014-01-10 13:28:45 +08:00
---- 具体的例子

比如我有一个 CoreDataTableViewController, 继承这个类的子类设置好一个 NSFetchedResultsController 并且实现 cofigureCell: 方法, 就可以从 CoreData 中装载数据, 并在 TableView 中显示.
不过 CoreDataTableViewController 只有显示数据的功能, 不能更改其中的数据. 所以就有了EditableCoreDataTableViewController, 它就具有添加, 删除的功能. 只要继承 EditableCoreDataTableViewController 的子类实现了 configureNewItem: 就可以向其中添加新的数据. 当然它也需要实现 CoreDataTableViewController 需要的 cofigureCell: 方法.

其实现在想想, 为什么要 EditableCoreDataTableViewController 类呢, 我也可以把 editable 这部分的功能放在 CoreDataTableViewController 这个里面...

---- 总结一下
希望对于和我有同样困惑的人有所帮助. 如果哪里说得不对, 还请各位指正. 同时也欢迎继续讨论. :D

-- 问题
"如果父类(A)和子类(A1)都有抽象方法, 需要继承他们的子类去实现, 如何设计接口使得继承 A1 的子类不仅仅知道需要实现 A1 的抽象方法, 还需要实现 A 的抽象方法? (子类相对父类就多一个功能的情况下)"
-- 我现在想到的解决方案
"由于子类与父类差异并不大, 所以子类的功能可以合并为父类的功能."
PS. 真是不知道为什么自己一开始要把这个功能分离出来... 害得自己苦苦思考了一天...

-- 问题扩展
"如果是在子类和父类差异较大的情况下(例如 UIScrollView 和 UITableView), 可能子类应该提供父类抽象方法的合理默认实现."

---- 回复

@dnnta

其实我也想过这样去做. 然后我去看了看 UITableViewController 的实现. UITableViewController 自身是遵循 UITableViewDataSource Protocol 的, 而且本身空实现了 UITableViewDataSource 所要求的 tableView:cellForRowAtIndexPath: 方法.

因为对于继承 UITableViewController 的子类来说, 如果没有实现 tableView:cellForRowAtIndexPath: 这个方法, 是不会报错的(warning/error). 但是如果控制的 TableView 需要这个方法的话, 会在运行时报错(报错大意是说这个方法应该返回一个 cell).

所以, 按照这样的思路去设计的话, 就和我在帖子正文中提到的 A 方法类似.


@railgun 您是说的 "@required"?
@PrideChung

这两个类都是抽象的意思是指, 他们有一部分方法需要继承他们的子类来实现. 其本身除了这些方法以外, 还有一些方法是他们自身实现的.

@fangzhzh 这两个类不是正交的概念, 应该是扩展吧.
railgun
2014-01-10 13:33:03 +08:00
@thedevil5032 呃,对,是@requested
fangzhzh
2014-01-10 13:38:09 +08:00
@thedevil5032 正交很好理解的. 比如一个是runable, 一个shoutable, 这两个概念没有重叠的,就是正交的.

如果是runable, 一个movable, 概念就可能有重叠,或者包含,就不是正交的.

其实我也是课本上学来的, 希望没有误导你.

我有个leader, 概念什么的都不懂, 但是实际工作给他的经验, 总是可以设计出分隔很好的系统.
repus911
2014-01-10 17:12:29 +08:00
建议 适配器模式
这个本来不是继承的问题,你不觉得抽象类继承抽象类很反人类吗?
alexrezit
2014-01-10 17:20:29 +08:00
@PrideChung
正解.

如果一定要用继承的话, 可以判断 self 的 class 是否是某个类的 subclass 然后根据条件判断丢 exception 啊.
PrideChung
2014-01-10 18:11:18 +08:00
我不太清楚你的业务逻辑,但在objc这种没有抽象类的语言里面搞这么复杂的继承关系无疑是自缚手脚,这年头连Java都在大喊“组合优于继承”了。你可以仔细想想是不是有什么特性可以分到别的类里面实现,然后通过不同的组合来得到不同的特性。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/96409

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX