Dan*_*ham 14 java inheritance overriding access-specifier
我有一个类结构,我希望基类中的某些方法可以从直接从基类派生的类中访问,但不能从派生类派生的类中访问.根据Java语言规范,可以覆盖继承方法的访问规范,使其更公开,但不是更私密.例如,这是我需要做的事情的要点,但是非法的:
// Defines myMethod
public class Base {
protected void myMethod() {}
}
// Uses myMethod and then hides it.
public class DerivedOne extends Base {
@Override
private void myMethod();
}
// can't access myMethod.
public class DerivedTwo extends DerivedOne {
}
Run Code Online (Sandbox Code Playgroud)
有没有办法实现这个目标?
编辑解释我为什么要这样做:
在这种情况下,类结构是数据处理和导入结构.它读入并解析充满表格数据的文本文件,然后将它们存储在数据库中.
基类是管理数据库处理部分的基表类.其中包含了相当多的功能,这些功能对于所有表类型都是通用的 - 因为一旦它们在数据库中,它们就变得统一.
中间类特定于要解析的文件中的表类型,并具有表解析和导入逻辑.它需要访问一些基类的数据库访问函数.
顶级类特定于表,并且只是以父类可以理解的方式初始化表的布局.此外,基类的用户不需要查看或访问中产阶级所执行的数据库特定功能.本质上,我想将这些函数仅显示在基类之上的一个级别而不是其他人.
我问,因为虽然我发布的代码是非法的,但可能还有其他方法可以实现同样的目的.我问是否有.
也许隐藏是错误的方式来表达这一点 - 我真正需要做的是将一些应该是基类私有的功能暴露给层次结构中一级的类.隐藏会实现这一点 - 但我可以看到隐藏是一个问题.还有另一种方法吗?
Dav*_*ims 17
我认为问题的本质就像你提出的那样暴露了对象模型的概念问题.您试图将各种不同的职责描述为"是一种"关系,而实际上您应该做的是描述"有一个"或"使用"关系.您希望从子类隐藏基类功能这一事实告诉我,这个问题实际上并没有映射到三层继承树.
听起来你正在描述一个经典的ORM问题.让我们再看看这个,看看我们是否可以将它重新映射到除了严格的"是"继承之外的其他概念,因为我认为你的问题不是技术性的,它是概念性的:
你说:
基类是管理数据库处理部分的基表类.其中包含了相当多的功能,这些功能对于所有表类型都是通用的 - 因为一旦它们在数据库中,它们就变得统一.
这可能更清楚,但听起来我们有一个类需要管理数据库连接和常见的数据库操作.遵循单一责任,我想我们已经完成了.你并不需要扩展这个类,你需要用手它需要使用它的功能的类.
中间类特定于要解析的文件中的表类型,并具有表解析和导入逻辑.它需要访问一些基类的数据库访问函数.
这里的"中产阶级"听起来有点像数据映射器.这个类不需要扩展前一个类,它需要拥有对它的引用,可能在构造函数或setter上作为接口注入.
顶级类特定于表,并且只是以父类可以理解的方式初始化表的布局.此外,基类的用户不需要查看或访问中产阶级所执行的数据库特定功能.本质上,我想将这些函数仅显示在基类之上的一个级别而不是其他人.
我不清楚为什么高级类似乎知道db模式(至少这是"初始化表的布局"这句话对我的意思),但同样,如果前两个类之间的关系是封装的话("有一个"/"使用"而不是继承("是一个"),我不认为这会是一个问题.
覆盖方法时,只能使其更公开,而不是更私密.我不知道为什么你用"一般"这个词
请记住,从最少限制到最严格限制:
public<protected<default<private
Run Code Online (Sandbox Code Playgroud)
是的," protected"是一个限制性较小的访问修饰符default(当没有使用修饰符时),因此您可以覆盖标记覆盖方法的默认方法protected,但不能相反.
可以:
您可以使用一个protected方法覆盖方法public.
不能:
你不能用一个public方法覆盖一个方法protected.
如果你这样做,那么从DerivedTwo的角度来看,DerivedOne不会是Base.相反,你想要的是一个包装类
//Uses myMethod but keeps it hidden
public class HiddenBase {
private final Base base = new Base();
private void myMethod();
public void otherMethod() {base.otherMethod();}
}
Run Code Online (Sandbox Code Playgroud)
你不能通过这种方式访问基地的受保护方法......