Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.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-在超类中注入资源,而不在基类中公开setter_Java - Fatal编程技术网

Java-在超类中注入资源,而不在基类中公开setter

Java-在超类中注入资源,而不在基类中公开setter,java,Java,也许这是一个简单的问题,但我还没有找到解决办法。我有这样的类配置: abstract class SuperA { Resource a; Resource b; public SuperA() { } public SuperA(Resource a, Resource b) { this.a = a; this.b = b; } protected Resource getResourceA() { ret

也许这是一个简单的问题,但我还没有找到解决办法。我有这样的类配置:

abstract class SuperA {
   Resource a;
   Resource b;

   public SuperA() {
   }

   public SuperA(Resource a, Resource b) {
      this.a = a;
      this.b = b;
   }

   protected Resource getResourceA() {
       return a;
   }

   protected Resource getResourceB() {
       return b;
   }

}

class BaseA extends SuperA {
   public method1() {
       Resource myResource = getResourceA();
   }
}

class Manager {
   public Manager() {
      // I want to instantiate BaseA and inject some resources, but can't do
      // it through the constructor
      BaseA baseA = new BaseA(/*can't place parameters*/);
      // I could use Setters, but this would expose the Setters to BaseA too...
      baseA.setResourceA(new Resource());
      baseA.setResourceB(new Resource());
   }
}
在这种情况下,我想将资源注入到超类中,而不向其基类公开任何Setter,也不继承构造函数,有什么方法可以做到这一点吗

更新-澄清


BaseA
类是API的扩展,我不希望其他用户有权修改实例化
BaseA
的核心引擎注入的资源。我希望
BaseA
使用资源而不是修改它们。

不允许访问构造函数基类的动机不清楚,而这显然是(IMHO)最好的选择:

class BaseA extends SuperA {  
    public BaseA() {
        super(new Resource(), new Resource()); // whatever
    }
}
或者有反射:

class Manager {
    public Manager() throws Exception {
        BaseA baseA = new BaseA();
        Field f = SuperA.class.getDeclaredField("a");
        f.setAccessible(true);
        f.set(baseA, new Resource()); // however you create a Resource
        // similar for field "b"
    }
}

一个选项是这样的setter,即“包可见”和“最终”

在方法声明中使用final关键字表示 方法不能被子类重写。从

然后使用“包私有”访问级别修饰符(后面不是确切的引用,而是解释)

(未说明“公共”、“私人”或“受保护”)这意味着 类本身可以看到/使用方法,类位于同一个确切的包中 可以查看/使用该方法,但子类和世界无法查看/使用 方法

单独使用“package private”可能会解决您的问题,但我会使用“final”只是为了使所需的行为更加明显,从而有助于将来的代码工作,等等

例如:

abstract class SuperA {
   // making these private also helps
   // because it limits child classes to ONLY use getters
   // they can't even 'fiddle with' the raw values
   private Resource a;
   private Resource b;

   // would you want this public? perhaps also no 'access-modifier' 
   // the 'exact' specifics of a lot of this class would depend on your
   // specific use case (But I'd think you would want this package-only too most likely)
   public SuperA() {
   }

   // note no 'access-modifier', means package use only.
   SuperA(Resource a, Resource b) {
      this.a = a;
      this.b = b;
   }


   // can also have the same with setters
   // again no 'access-modifier' 
   final setResourceA(Resource a){ this.a = a;}
   final setResourceB(Resource b){ this.b = b;}

   public final Resource getResourceA() {
       return a;
   }


   public final Resource getResourceB() {
       return b;
   }

}

这将允许您的库访问这些方法,但不允许子类或“world”

为什么您不想使用构造函数?我可以使用构造函数,但需要从基类继承它,我希望保留基类,而不允许访问更改资源。您所说的需要继承它是什么意思?如果
BaseA
扩展了
SuperA
,则它可以访问所有可见的
SuperA
构造函数。此外,如果资源是私有的,并且任何setter都是私有的,则一旦构建了BaseA的对象,BaseA就不能更改资源。它们必须传递给构造函数,但是构造的对象不能改变它们。不,它不能。
Manager
类试图在
BaseA
中获取一个实例,但除非
BaseA
覆盖它,否则它无法看到
SuperA
的构造函数。这就是问题所在。为什么要投反对票呢???谢谢你的回答。是的,反思将是一个解决方案。事件,但如果它是一个高流量例程,则会带来性能损失。@Joe请参阅编辑以回答某些代码的问题。性能惩罚并不是那么高——如果它是你需要的解决方案,就用它。是的,我会考虑的。我需要验证这部分代码中的反射成本。在一个不太易转换的代码中,这不会是一个问题。谢谢。@Joe我刚刚对上面的反射基代码做了一个快速性能测试:上面的代码不到10微秒(0.01毫秒)。除非你每秒要创建数千个这样的东西,否则性能不应该是个问题。是的,它只允许核心api访问setter,而不允许子类或其他任何人。谢谢。如果
管理器
类在不同的包中,但在同一个jar文件中,该怎么办?我不得不将
Manager
类移动到
SuperA
的同一个包中,以使其正常工作。然后,如果可以,可以重构库。因为这是提供他想要的功能的正确方式。在我看来,使用反射或其他方法不移动类似乎有点短视。当然,可能有一个有效的边缘情况(特别是在遗留代码或已经大量使用包可见性的代码中,并且您需要一个完整的重构),但我仍然认为这种方法对于“一般情况”是最好的