I've got two class: GraphNode and BTNode extends GraphNode. I've got method:
public GraphNode.addChild(GraphNode node)
as GraphNode may have many children
and two methods:
public BTNode.addLeftChild(BTNode left)
public BTNode.addRightChild(BTNode right)
as BTNode may have only two children
How may I restrict public access to inherited addChild(GraphNode node) method from BTNode class? I wouldn't like to have that publicly accessible from that level (while remaining public access from GraphNode class)?
If you extend (or implement) from a class (or interface) then the parent will specify the whole signature of a method. There is nothing you can change about it, you will always need to have the method public if your parent specifies it as public.
Otherwise you would run into problems when casting like ((Parent) child).theMethod(). The object itself is child but the view gets reduced to the Parent class. The method gets invoked from the child class, so it would be private although you casted it to Parent which specified it as public.
However you could do something like:
public class Child extends Parent {
#Override
public void theMethod() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
private void otherMethod {
// Do something
}
}
But note that saying "I am extending class XY but not supporting all of its methods" is not the best design. It is a sign that the parent class (or other parts of the architecture) could have been structured more modular in the first place.
It is not possible to reduce the visibility of a method in subclass. The subclass need to be a valid instance of the base class.
As you can see in the previous answers, it is not possible to change visibility of public methods in the child classes. But in case of you are designer of GraphNode class, you could use a little bit another class hierarchy:
public abstract class BaseNode {
protected final Map<String, GraphNode> children = new HashMap<>();
protected void addChild(String id, GraphNode node) {
children.put(id, node);
}
}
public class GraphNode extends BaseNode {
public void addChild(GraphNode node) {
children.put(String.valueOf(System.currentTimeMillis()), node);
}
}
public class BTNode extends BaseNode {
private static final String LEFT = "left";
private static final String RIGHT = "right";
public void addLeftChild(BTNode node) {
addChild(LEFT, node);
}
public void addRightChild(BTNode node) {
addChild(RIGHT, node);
}
}
Related
How do you hide the following class behind an interface (and instantiate it using a factory)?:
public class TreeNode {
private List<TreeNode> children;
private TreeNode parent;
public void addChild(TreeNode newChild) {
children.add(newChild);
newChild.setParent(this);
}
public TreeNode getParent() {
return parent;
}
public void removeChild(TreeNode child) {
children.remove(child);
child.setParent(null);
}
void setParent(TreeNode newParent) {
if(parent != null) {
parent.removeChild(this);
}
parent = newParent;
}
}
Suppose you were to rename the class to TreeNodeObj and have it implement the TreeNode interface:
class TreeNodeObj implements TreeNode {
private List<TreeNode> children;
private TreeNode parent;
public void addChild(TreeNode newChild) {
children.add(newChild);
newChild.setParent(this);
}
... etc. ...
}
public interface TreeNode {
public void addChild(TreeNode newChild);
public void removeChild(TreeNode child);
public TreeNode getParent();
}
public class NodeFactory {
public static TreeNode createTreeNode() {
return new TreeNodeObj();
}
}
This code doesn’t compile, because setParent() isn’t defined in the TreeNode interface (since it should not be called directly and should not be exposed outside the package).
The only solution I can think of is to make the following modification:
public interface TreeNode extends TreeNodePackageAccess {
public void addChild(TreeNode newChild);
public void removeChild(TreeNode child);
public TreeNode getParent();
}
interface TreeNodePackageAccess {
void setParent(TreeNode newParent);
}
class TreeNodeObj implements TreeNode {
…[previous code]…
public void setParent(TreeNode newParent) {
// this method is made public in order to implement TreeNodePackageAccess
…[previous code]…
}
}
Is there a better way to accomplish this than with the above strategy? (Also, with the above strategy, setParent() is still accessible from outside the package via reflection, so technically, you don't even get package-level encapsulation with it.)
How do you hide the original class behind an interface, given that it requires a package-level method that shouldn’t be exposed?
Just cast it to the implementation class where needed. If any implementation of TreeNode is not a TreeNodeObj, throw an exception that indicates it came from an invalid provider.
Java SE already does this. From the documentation of the java.nio.file package:
Unless otherwise noted, invoking a method of any class or interface in this package created by one provider with a parameter that is an object created by another provider, will throw ProviderMismatchException.
So your other classes in that package can do things like:
#Override
public void add(TreeNode node) {
if (!(node instanceof TreeNodeObj)) {
throw new WrongProviderException(
"Argument was created by a different provider: " + node);
}
TreeNodeObj obj = (TreeNodeObj) node;
obj.setParent(parent);
}
How do you hide a class behind an interface when that class contains a package-level method?
As posed, there's nothing special required here. You can abstract any number, including zero, of a class's public methods with an interface. It is not necessary in any general sense that all methods of the class be mirrored as abstract methods of the interface.
But you seem to mean that you want to represent one or more package-access methods in an interface, and this is not possible. Interface methods may be only public or private, and private methods are not abstract. The implementation of an abstract method cannot narrow its access, so the implementation of an abstract interface method must be public.
Your idea to split the interface into a package-access superinterface and a public subinterface does not help in any way, even if you were willing to make the implementation method public after all. Any method declared by the superinterface is inherited by the subinterface and can be accessed through it.
I have three classes. I want to execute the CodeBlock2 in the Parent class's execute method conditionally based off of a flag I would be setting while calling this method through MyChild class.
For the legacy purposes, modifying the signature of the execute method in Parent class to have an extra boolean argument is not possible.
Q1. In CPP, I have used lambda functions to achieve similar effects; which in my experience, involved a lot of code modifications all across the package wherein equivalent of Parent class was used. I'd refrain from such given the criticality and coverage of my change. Does Java have some similar or easier way do achieve this?
Q2. I think using instance variable with a flag in the Parent class would also be possible, maybe not as elegant. Could someone chime in on this solution as well?
I would really appreciate your opinions. There are some related but not quite similar questions 1, 2.
public abstract class Parent extends GrandParent
{
#override
public void execute(String A)
{
// CodeBlock1
// CodeBlock2 // I wanna put this under if condition based on a flag in MyChild
// CodeBlock3
}
}
public class Child extends Parent
{
#override
protected boolean someMethod()
{
// code
}
}
public class MyChild extends GrandParent
{
#override
public boolean execute(String A)
{
String B = "123";
child.execute(B);
// child.execute(B, true); // what I wanna do
}
private Child child;
}
If you can extract CodeBlock2 into a separate method in the Parent class, the below would work:
public abstract class Parent extends GrandParent
{
#Override
public void execute(String A)
{
// CodeBlock1
codeBlock2(); // I wanna put this under if condition based on a flag in MyChild
// CodeBlock3
}
protected void codeBlock2() {
// CodeBlock2
}
}
public class MyChild extends Parent
{
#Override
protected void codeBlock2() {
if(condition) {
super.codeBlock2();
}
}
}
You can not change the method signature of the parent's method from child,
you can define a boolean flag in the parent with access modifier protected and change
in the child and calling the parent method using super.execute(A)
public abstract class Parent extends GrandParent {
protected boolean enableCodeBlock2;
#override
public void execute(String A) {
// CodeBlock1
if (enableCodeBlock2){
// CodeBlock2 // I wanna put this under if condition based on a flag in MyChild
}
// CodeBlock3
}
}
, And in the child
public class Child extends Parent {
#override
public void execute(String A) {
enableCodeBlock2 = true;
super.execute(A);
}
}
I am working on a problem where I implement different Linked lists. All the list classes include two inner classes; a Node-class and an Iterator-class.
These inner classes are entirely identical to each other. In the Iterator-class, some of the methods rely on accessing information from the outer class, which works fine. Is there a way to do this in java, so that I would not need to include the very same code in all my different list-classes? I feel clueless - I just don't know where to look.
This is what my Node-class looks like:
class Node{
Node next;
Node previous;
private T data;
Node(T inn){
data = inn;
}
public Node getNesteNode(){
return next;
}
public T getData(){
return data;
}
}
Edit: I realize the Node class is relying entirely on itself.
Here is my simple Iterator:
class LenkeListeIterator implements Iterator<T>{
private int field = 0;
Node denne = forste;
#Override
public boolean hasNext() {
return field!= storrelse();
}
#Override
public T next() {
T data = denne.getData();
denne = denne.getNesteNode();
field++;
return data;
}
}
By definition, an inner class is an intrinsic part of the class containing it. It can only be shared with subclasses, not peers or classes outside the hierarchy of the parent class entirely.
There's nothing in your Node class that requires it to be an inner class, so you could just make it standalone. But if there were something that made it need to be an inner class, you could put all the parts that don't into a standalone class that is then subclassed in each of the parent classes to provide it with access to the parent's inner data.
E.g. (roughly):
abstract class Example {
protected int something;
public void logic() {
SomeType data = this.getParentData();
/* ...do something with `data`... */
}
abstract protected SomeType getParentData();
}
Then an inner class in, say, Container would subclass it and provide getParentData.
class Container {
private SomeType data;
class ContainerExample extends Example {
protected SomeType getParentData() {
return data;
}
}
}
I'm not really sure how to describe this pattern that i want, but I would like something like this:
public abstract class Parent {
protected abstract boolean foo = false; //this doesn't compile
}
public class Child1 extends Parent {
protected boolean foo = true;
}
how do i do this?
Imagine i have 1 Parent class, but like 20 Child classes. for the vast majority of the children, the foo should be false. However, Child1 (and a few others) is the weird one with foo = true;.
what is the most proper OO Design and yet code effecient way to do this?
You can do this with a constructor or two:
public abstract class Parent {
protected boolean foo;
protected Parent() {
this(false); // initialize foo to default value
}
protected Parent(boolean fooValue) {
this.foo = fooValue;
}
}
public class Child1 extends Parent {
public Child1() {
super(true);
}
}
public class Child2 extends Parent {
// no explicit super(boolean) call in c'tor gives foo the default value
}
First, instance variables cannot be abstract, only methods can.
To have overriding behavior, you need methods. I would define a method, say, isFoo in Parent that is defined to return false. No subclasses would need to override it, except for the "weird one"(s), which can override it to return true.
Alternatively, you can have a subclass of Parent called WeirdOne (doesn't have to be that name of course). The only thing it does is override isFoo to return true. Then Child1 and any other "weird" classes subclass WeirdOne. This way, it's only overridden in one place.
I think you need to do like this
public abstract class Parent {
protected boolean check = false;
}
public class Child extends Parent
{
public void method()
{
this.check=true;
}
}
// You can put it in constructor also
If you want to extend the Parent class using Child1 class, you have to type:
public class Child1 extends Parent {
}
About the foo parameter, you can't set it abstract since is not a function (that is, only functions can be declared abstract). You can, however, override it in subclasses.
public abstract class Parent {
protected boolean foo = false;
}
public class Child1 extends Parent {
#Override
protected boolean foo = true;
}
Don't use a field then. Look at this combination of classes:
public abstract class Vehicle {
public abstract boolean isAerial();
}
public abstract Flyer extends Vehicle {
#Override
public final boolean isAerial() {
return true;
}
}
// Add Airplane, Helicopter, Dirigible, Rocket, etc.
public abstract Terrestrial extends Vehicle {
#Override
public final boolean isAerial() {
return false;
}
}
// Add Car, Truck, Boat, Bicycle, etc.
I'm building a base/parent class in Java that's going to have several methods for creating the class itself and I'm wondering if there's any way to have the parent class return instances of the child class instead of returning instances of the parent class that then have to be cast to the child?
For example, here's my parent class:
public abstract class SFObject
{
// Variables
protected String mID;
protected String mName;
// Function called to create ourselves from a DiffObject
public abstract SFObject CreateFromDiffObject(DiffObject object);
// Function called to create a list of ourselves from a query
public List<SFObject> CreateListFromQuery(Connection connection, String query)
{
// Run the query and loop through the results
ArrayList<SFObject> objects = new ArrayList<SFObject>();
for (DiffObject object : connection.Query(query))
objects.add(CreateFromDiffObject(object));
return objects;
}
}
If I create a child class based on my SFObject class, the two functions in my child class will still return an SFObject (that needs to be cast to my child class type) or a list of SFObjects (that need to be individually cast to my child class type). Is there any way (maybe using Reflections) to have my child class returns instances of itself as itself and not as SFObjects?
What you are describing is known as a covariant return type.
Class A {
A getInstance() { ... }
}
Class B extends A {
#Override
B getInstance() { ... }
}
This has been allowed since Java 1.5.
If you place the child class object inside of the parent object, methods called will run from the child class. But it will look like the parent object on the surface
public class A{
method 1(){//do some stuff}
method 2(){//do some stuff}
}
public class B extends A{
method 1(){super.method 1()
//do some other stuff}
method 2(){super.method 2()
//do some other stuff}
}
public class test{
A a = new B();
//any method called on 'a' will come from the child class
// But 'a' is the parent object
}
Not sure if I really understand your Problem correct because it sounds to me lke this:
class p
{
public static p createParent()
{
return new p();
}
public static c createChild()
{
return new c();
}
}
Of course it doesn't have to be static, just thought of some kind of factory.
Exactly for this functionalities are proposed the factory methods, as you already implemented. In the child class you can change the return type without offending the method declaration. A sample for your case would be something like:
public abstract class SFObject {
// Variables
protected String mID;
protected String mName;
// Function called to create ourselves from a DiffObject
public abstract SFObject CreateFromDiffObject(DiffObject object);
// Function called to create a list of ourselves from a query
public List<? extends SFObject> CreateListFromQuery(Connection connection, String query) {
// Run the query and loop through the results
ArrayList<SFObject> objects = new ArrayList<SFObject>();
for (DiffObject object : connection.Query(query))
objects.add(CreateFromDiffObject(object));
return objects;
}
}
class SFObjectChild extends SFObject {
#Override
public SFObjectChild CreateFromDiffObject(DiffObject object) {
SFObjectChild result = new SFObjectChild();
//...
return result;
}
#Override
public List<? extends SFObjectChild> CreateListFromQuery(Connection connection,
String query) {
return null;//..;
}
}
This is acceptable because the return type of the children class is still a kind of (hierarchical speaking) the parent.
Be aware of java code conventions (methods in camel case starting with low, e.g. createFromDiffObject).