Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:有没有办法强制实现私有方法?_Java_Oop - Fatal编程技术网

Java:有没有办法强制实现私有方法?

Java:有没有办法强制实现私有方法?,java,oop,Java,Oop,我有5或6个类,我想让它们在内部遵循相同的基本结构。实际上,这些类应该遵循的大多数方法只是用于函数本身,所以我真的希望这些方法是私有的 有没有办法做到这一点?我知道接口可以很好地工作,但它们不会接受私有成员,也不允许您在实现的方法中重新定义范围。有什么解决办法吗 谢谢创建一个抽象基类,概述结构和公共流。为流中必须由继承类实现的步骤指定抽象方法。我认为最接近的方法是使用abstract类和abstract受保护的方法: abstract class A { protected abstra

我有5或6个类,我想让它们在内部遵循相同的基本结构。实际上,这些类应该遵循的大多数方法只是用于函数本身,所以我真的希望这些方法是私有的

有没有办法做到这一点?我知道接口可以很好地工作,但它们不会接受私有成员,也不允许您在实现的方法中重新定义范围。有什么解决办法吗


谢谢

创建一个抽象基类,概述结构和公共流。为流中必须由继承类实现的步骤指定抽象方法。

我认为最接近的方法是使用
abstract
类和
abstract
受保护的
方法:

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();
}

这样,您就可以允许子类用特定的行为填充私有公共函数。

嗯,私有函数不能被任何其他类调用。那么,在不同的类中使用同名的私有函数有什么意义呢

使用标记为final的方法创建一个抽象基类,该方法描述包含私有方法的公共流。将它标记为final意味着它不能被子类扩展,因此只要调用代码使用它,业务逻辑就会被强制执行。可以通过将方法标记为受保护来创建扩展点。例如,假设您有一个表示零售商店的类

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);

}

“throw MethodNotImplementedException();”可能是一个有用的构造。

创建一个大纲“common”类,其中包含所有私有方法

然后创建5或6个类,每个类上都有一个“common”类型的字段。 当然,您不能调用私有方法(但您说这些方法实际上是类的内部方法)——当然,您还必须公布一些公共方法来改变状态

public class common { 
    private method1() { ; }
    private method2() { ; }
    public other() { ; }
...
}

public class myclass1 { 
    common commonMethods;
}

public class myclass2 { 
    common commonMethods;
}
甚至(假设“公共”的定义如上所述):

因此,在5或6个子类中的每一个子类上都有一个(受包保护的)“commonMethods”字段作为“free”


在对该线程进行后续讨论后,作者似乎并不真正想要共享逻辑:本质上只是方法签名,因此该答案不符合该要求。

在编译时无法强制执行它,但是您可以编写一个单元测试或一个简单的程序来测试使用反射的方法是否存在

我假设您这样做是为了使课程在美学/设计方面保持一致。如果你是出于其他原因这样做的,你应该真正使用其他人建议的抽象保护方式

下面是一些代码,可以让您开始使用这种工具/单元测试(您至少应该改进错误消息,我建议您使用单元测试,而不是我这里介绍的):

import java.lang.reflect.Method;
导入java.lang.reflect.Modifier;
公共班机
{
公共静态void main(字符串[]args)
{
检查(B.class,Modifier.PRIVATE,void.class,“doit”,新类[]{int.class});
检查(C.class,Modifier.PRIVATE,void.class,“doit”,新类[]{int.class});
}
私人静态无效检查(最终课程分类,
最终整型修饰符,
最后一类返回类型,
最后一个字符串名,
最终类[]参数)
{
尝试
{
最终方法;
方法=clazz.getDeclaredMethod(名称、参数);
if(method.getModifiers()!=修饰符)
{
System.out.println(“修饰符不匹配”);
}
if(method.getReturnType()!=returnType)
{
System.out.println(“返回类型不匹配”);
}
}
捕获(最终NoSuchMethodException ex)
{
System.out.println(“找不到方法”);
}
}
}
接口A
{
void foo();
}
B类
实施
{
公共图书馆
{
doit(0);
}
私有无效doit(最终整数x)
{
}
}
C类
实施
{
公共图书馆
{
doit(0);
}
私有整数doit(最终整数x)
{
返回(5);
}
}

如果抽象保护真的没有得到足够的保护,我想知道问题是什么。在任何情况下,一个类似于monojohnny的替代方案是使用策略模式。这可确保:

  • 派生类必须定义行为
  • 定义行为后,派生类无法访问该行为
  • 实例无法访问彼此的行为
例如,尽管没有汽车印章,但仍为借用汽车隐喻表示歉意:

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());
    }
}

看看XDepend,它使用反射根据编译的代码创建数据库

它的目标是软件架构师,他们希望能够快速检查潜在的大型编译代码库,寻找潜在的问题区域。它为类之间的关系、圈复杂度、耦合等提供了内置的报告和可视化

此外,它还包括内置的类似sql的查询语言“CQL”(用于“代码查询语言”)。使用CQL,您可以定义自己的报告。您可能应该能够使用它来定义违反您描述的规则的报告。此外,还可以使用注释将CQL查询直接嵌入到代码中

我没有研究过它,但使用了它的.NET等价物“NDepend”,它是一个非常酷的工具


当然,您也可以编写自己的自定义工具,该工具使用反射来检查您的特定规则。XDepend可能仍然值得一看——它应该更加灵活。

是否可以让所有类都继承fr
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);
    }
}
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());
    }
}
package com.some.car.pkg;

interface Car
{
    public void gas();
    public void brake();
}
public @interface Car { }