受保护的字段对子类不可见
Posted
技术标签:
【中文标题】受保护的字段对子类不可见【英文标题】:Protected fields not visible to subclasses 【发布时间】:2011-06-22 10:05:04 【问题描述】:我正在编写一个直接扩展android.view.View
的自定义视图。如果我尝试访问字段mScrollX
或mScrollY
,我会看到该字段“无法解析或不是字段”的错误。 source code for android.view.View 具有 mScrollX、mScrollY 和声明为 protected
的类似变量。我的直接子类如何无法访问其父类的受保护字段? (ScrollView 这样的类显然可以。)
附:我意识到我可以打电话给getScrollX()
,但我想更新这些字段;打电话给setScroll()
有我不想要的副作用。
【问题讨论】:
奇怪的是,子类,即使在其他包中,也可以访问其超类的受保护变量。我猜你使用的是错误的版本。你能展示一些你的代码吗? 【参考方案1】:这是因为它们不是 Android SDK 的一部分。
这里是mScrollX
的源代码:
/**
* The offset, in pixels, by which the content of this view is scrolled
* horizontally.
* @hide
*/
@ViewDebug.ExportedProperty(category = "scrolling")
protected int mScrollX;
您会注意到@hide
注释。这意味着这不是 Android SDK 的一部分。创建 Android SDK 的构建过程部分不会将此数据成员包含在您正在编译的 android.jar
文件中的 android.view.View
存根版本中。
@hide
注释用于出于内部目的需要公开或受保护但不被视为 SDK 开发人员应该使用的东西。
请为您遇到的任何问题寻找其他解决方案。
【讨论】:
嗯,有趣!所以套用基本原理:“我们懒得理清适当的封装,所以我们颠覆了语言。”... 我注意到了@hide
标签。我认为这就是为什么 mScrollX
没有出现在 JavaDocs 中的原因(比如 proposed @exclude
tag,它取代了 @hide
)。我没有意识到 SDK 是 API 的存根版本。
我无法理解的一件事是 View 类的受保护变量在 ScrollView 类中被访问。这怎么可能 ?层次结构是 - ScrollView 扩展 FramLayout 扩展 ViewGroup 扩展 View。因此,View 类的 protected 变量只能在 ViewGroup 中访问。【参考方案2】:
这很简单:注意这些变量上方的@hide 注释。 它是一个特定于 Android 的注释,它对公共 SDK 隐藏字段/方法。这就是你不能直接访问它们的原因。
Romain Guy mentioned it in这个帖子。
【讨论】:
这令人不安。开源有什么意义?所以人们可以阅读源代码并了解发生了什么。但是这里发布的消息是假的?不是生产中使用的那个?这也是可以接受的,如果它是透明的。我不在乎JDK源是否是真实的,但我从阅读中获得的任何信息在真实系统中都必须是真实的。 你必须明白开源的含义。首先,您可以直接从源代码构建自己的 Android 版本,对其进行任何修改,并使用每个方法或字段,无论是否隐藏。这就是手机制造商所做的,以及社区中的一些定制 ROM 厨师。开发人员可以从 Android 开源的另一个方面受益,那就是通过源代码了解幕后工作原理,对我来说,这与文档本身一样重要。 隐藏某些字段或方法的情况通常是以下两种情况之一: 1.可能会在未来的SDK版本中发生变化,因此他们希望减少应用程序不兼容的机会,节省您,开发人员需要大量维护您的应用程序,并且 2. 像在您的情况下直接使用这些字段可能会干扰 API 在内部如何正常工作。【参考方案3】:您可以尝试使用反射设置字段:
import java.lang.reflect.Field;
// ...
try
Field scrollXField = View.class.getDeclaredField("mScrollX");
scrollXField.setAccessible(true);
scrollXField.set(this, myNewValue);
catch (Exception ex)
// oops, android changed the implementation. sucks to be you.
但是请注意,当您执行此操作时,您依赖于未记录和不受支持的行为,因此您应该为某些设备或未来版本中出现的问题做好准备。
【讨论】:
以上是关于受保护的字段对子类不可见的主要内容,如果未能解决你的问题,请参考以下文章