我有5或6个类,我希望它们在内部遵循相同的基本结构。实际上,这些类应该遵循的大多数规则仅供函数本身使用,因此我真的希望这些方法是私有的。
有没有办法实现这一点?我知道接口非常适合,但它们不会使用私有成员,并且不允许您重新定义实现方法中的作用域。有没有解决这个问题的方法?
谢谢
我有5或6个类,我希望它们在内部遵循相同的基本结构。实际上,这些类应该遵循的大多数规则仅供函数本身使用,因此我真的希望这些方法是私有的。
有没有办法实现这一点?我知道接口非常适合,但它们不会使用私有成员,并且不允许您重新定义实现方法中的作用域。有没有解决这个问题的方法?
谢谢
我认为最接近的方法是使用一个带有抽象受保护方法的抽象类:
abstract class A {
protected abstract void foo();
}
class B extends A {
protected void foo() {}
}
为了定义共有的逻辑,您可以从父类的私有方法中调用受保护的方法:
abstract class A {
private void bar() {
// do common stuff
foo();
}
protected abstract void foo();
}
这样,您可以允许子类使用特定的行为填充私有的公共模板方法。
创建一个抽象基类,概述结构和常见流程。为流程中必须由继承类实现的步骤指定抽象方法。
嗯,私有函数不能被任何其他类调用,甚至子类也不行。那么在不同的类中使用相同名称的私有函数有什么意义呢?
在编译时没有办法强制执行它,但是您可以编写一个单元测试或简单的程序来使用反射测试方法的存在。
我假设您这样做是为了使类在美学/设计方面保持一致。如果您出于其他原因而这样做,您应该真正使用其他人建议的抽象受保护方式。
以下是一些代码,可帮助您开始编写此类工具/单元测试(您应该至少改进错误消息,并且我真的建议使用单元测试而不是我在此处所做的内容):
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Main
{
public static void main(String[] args)
{
check(B.class, Modifier.PRIVATE, void.class, "doit", new Class<?>[] { int.class });
check(C.class, Modifier.PRIVATE, void.class, "doit", new Class<?>[] { int.class });
}
private static void check(final Class<?> clazz,
final int modifiers,
final Class<?> returnType,
final String name,
final Class<?>[] params)
{
try
{
final Method method;
method = clazz.getDeclaredMethod(name, params);
if(method.getModifiers() != modifiers)
{
System.out.println("modifiers do not match");
}
if(method.getReturnType() != returnType)
{
System.out.println("return type does not match");
}
}
catch(final NoSuchMethodException ex)
{
System.out.println("could not find method");
}
}
}
interface A
{
void foo();
}
class B
implements A
{
public void foo()
{
doit(0);
}
private void doit(final int x)
{
}
}
class C
implements A
{
public void foo()
{
doit(0);
}
private int doit(final int x)
{
return (5);
}
}
创建一个名为“common”的概要类,并将所有私有方法放在其中。
然后创建5或6个类,每个类都有一个类型为“common”的字段。 当然,您无法调用私有方法(但是您说这些方法实际上是类内部的),您必须公开一些公共方法来改变状态。
public class common {
private method1() { ; }
private method2() { ; }
public other() { ; }
...
}
public class myclass1 {
common commonMethods;
}
public class myclass2 {
common commonMethods;
}
public class template {
common commonMethods;
}
public class myclass1 extends template {
...
}
因此,在每个5或6个子类中,您都可以免费获得一个(包保护的)“commonMethods”字段。
在对此线程进行后续讨论后,似乎作者实际上并不想共享逻辑:只是方法签名基本上,因此,这个答案不符合该要求。
虽然接口方法本身必须始终是公共的,但您可以将接口设为包私有并将所有Car(例如)的实现保留在同一个包中。
package com.some.car.pkg;
interface Car
{
public void gas();
public void brake();
}
以上仅供参考。
private final void doTransaction() {
float amountDue;
// a protected or abstract method that extenders can override
Collection items = this.unloadShoppingCart();
for (Object item : items) {
// another protected or abstract method
amountDue += this.getPrice(item);
}
// your private method
amountDue += this.getSalesTax(amountDue);
}
public interface GearBoxStrategy {
public void changeGear(int newGear);
}
abstract public class Car {
private GearBoxStrategy gearBox;
public Car(GearBoxStrategy g) {
this.gearBox = g;
}
public void accelerate(double targetSpeed) {
int gear = getTargetGear(targetSpeed):
gearBox.shift(gear);
}
}
public class AutomaticTransmissionCar {
public AutomaticTransmissionCar() {
super(new AutomaticTransmissionGearBoxStrategy());
}
}
public class ManualTransmissionCar {
public ManualTransmissionCar() {
super(new ManualTransmissionGearBoxStrategy());
}
}
使用 "throw MethodNotImplementedException();" 可能是一个有用的结构。
看看XDepend,它使用反射根据您编译的代码创建数据库。
该工具旨在为软件架构师提供快速检查潜在问题的编译代码库。它具有内置报告和可视化功能,例如类之间的关系、圆形复杂度、耦合等等。
此外,它还包括一个内置的类似于SQL的查询语言"CQL"(用于"代码查询语言")。使用CQL,您可以定义自己的报告。您可能应该能够使用它来定义违反您描述的规则的报告。此外,您还可以使用注释将CQL查询直接嵌入到您的代码中。
我没有研究过它,但已经使用了它的.NET等效工具'NDepend',这是一个非常酷的工具。
当然,您也可以编写自己的定制工具,使用反射来检查您特定的规则。不过,XDepend仍然值得一看——它应该更加灵活。