My question today is about creating an object, and what other classes with have access to its methods. I am trying to learn about threading, but since JPanels don't support threads I have gotten all confused.
I create a simplified class like this:
public class MyMethodClass {
public MyMethodClass () {
MyClass myClass = new MyClass();
}
public void MyMethod() {
//do something with the variables
}
}
so I now have a new class object called myClass (MyClass is another class, its content not important). As they are all public, does myClass have access to MyMethod?
If not, is there a way to pass a copy MyMethodClass to myClass so that it can use myMethod, knowing that MyMethodClass created myClass in the first place?
If the class MyClass was a nested class, does it get access to MyMethod?
MyClass will not be able to access methods within MyMethodClass unless it creates an instance of it and in this case, that's a bad idea.
You could could pass MyClass an instance of MyMethodClass via its constructor or a setter method, but you'd actually be better using a common interface, which would decouple the two classes and improve its reusability
Start by defining the contract between the two class (as an interface)...
public interface SomeMethods {
public void MyMethod();
}
Add the ability to pass an implementation of SomeMethods to MyClass via it's constructor or setter method...
public class MyClass {
private SomeMethods someMethods;
public MyClass(SomeMethods someMethods) {
this.someMethods = someMethods;
}
public void someWork() {
someMethods.MyMethod();
}
}
Have MyMethodClass implement the SomeMethods interface and pass a reference of itself to MyClass
public MyMethodsClass implements SomeMethods {
public MyMethodClass () {
MyClass myClass = new MyClass(this);
}
#Override
public void MyMethod() {
//do something with the variables
}
}
Just beware, it's generally not considered a good idea to pass this to other classes or methods from within the constructor, as the state of the object may not be fully realised and some value that the methods/classes rely on may not yet be initialised.
Related
I have an Interface (call it Planet) whose implementation class is protected, and I can not change access modifier for the same. However, I need to call the methods of the implementation class inside of my main class. For example, in the implementation class, I have: public void orbit() {distance++;}
I have tried: private Planet planet = new PlanetImpl, but since the PlanetImpl class is protected and in a different package, it can't find it, making the statement invalid. I have also tried leaving it null, like this
Planet planet; planet.orbit();
but it throws a NullPointerException. Is it possible to call the methods without directly referencing the implementation class?
Using anonymous inner class we can do it. Anonymous classes can implement interfaces, and i think at that time only you'll have a chance to see a class implementing an interface without the "implements" keyword.
interface Planet {
public void orbit();
}
class PlanetMain {
private Planet p = new Planet () {
public void orbit() {
System.out.println("interface Planet class executed");
}
};
}
In your case you have to create an object of that PlanetImpl class somewhere to execute the method. The interface has only the definition of that method, not the implementation.
Assuming that private/protected impl class is inner class. To call the orbit() method which is a instance method(not static), You need to create a public static factory method in the outer class and call the orbit using the instance provided by this method.
basic code example
public class PlanetImplholder{
public static Planet getInstance(){
return new PlanetImpl();
}
private static class PlanetImpl implements Planet{
#Override
public void orbit() {
System.out.println("111");
}
}
}
call the method from anywhere like below.
Planet planet = PlanetImplholder.getInstance();
planet.orbit();
Is it possible to call the methods without directly referencing the implementation class?
NO, THIS IS NOT POSSIBLE. Interface and implementation class are just declaration. To use it, you have to create class or interface instance with new. But you cannot do it, because you want to use logic of PlanetImpl, which is protected.
I think, that you do not want to implement your own class declaration and then create and use new instance of it. I think, that only one way is using reflection. Using it, you can create an instance of protected class PlanetImpl and then use it in normal ways.
Class<Planet> cls = (Class<Planet>)Class.forName("<full PlanetImpl class name, inclusing package>");
Constructor<Planet> constructor = cls.getDeclaredConstructor();
constructor.setAccessible(true);
Planet planet = constructor.newInstance();
planet.orbit();
I can't test it right now, but you can use reflection to access the class properties of an object.
Planet planetImpl = factory.getPlanet(); // getPlanet() returns PlanetImpl
Method orbit = planetImpl.getClass().getDeclaredMethod("orbit");
orbit.setAccessible(true);
orbit.invoke(planetImpl);
This may not work if a SecurityManager prevents access to PlanetImpl.
I have a method in an abstract class that calls an abstract method, for which the subclasses must provide the implementation.
public abstract class AClass {
public void foo() {
...
fooToImplement();
...
}
// DON'T CALL THIS METHOD, ONLY PROVIDE IMPLEMENTATION!
protected abstract void fooToImplement();
}
I want to make sure that the subclasses don't call fooToImplement(), they should always use foo() instead. The behavior is something like a "private abstract" method, but that's not possible in Java.
Is there some alternative? Thanks!
If you don't want your subclasses to be able to call this method you could use strategy: Extract the behavior of the method into an interface and pass an implementation of this interface to the object. E.g.
IStrategy {
public void fooToImplement();
}
AClass {
public AClass(IStrategy impl) {...}
public void foo() {
...
strategy.fooToImplement();
...
}
}
Delegation instead of inheritance. In java 8 this would be a little bit easier.
If your implementation of IStrategy would need access to the data of the object AClass, you could try to implement it as an inner class.
The method has to be visible by your subclass if you want it to be overriden.
You have to use a class witch does not extends AClass as caller.
public class BClass extends ACLass {
#Override
protected void fooToImplement() {
System.out.println("override me im famous");
}
}
public class CClass {
private BCLass bInstance;
public void doSomething(){
bInstance.foo();
// !!! NO ACCESS TO fooImplement()
}
}
Since fooToImplement() needs to be visible to subclasses to be implemented there and there's no way to distinguish between "implement visibility" and "execution rights", you can't do this by inheritance.
You could however combine your object with another object that contains fooToImplement() by composition:
interface FooImplementation {
void fooToImplement(AClass a);
}
public abstract class AClass {
private final FooImplementation fooImpl;
protected AClass(FooImplementation fooImpl) {
this.fooImpl = fooImpl;
}
public void foo() {
...
fooImpl.fooToImplement(this);
...
}
}
That wouldn't prevent anyone from outside the class from using yourFooImpl.fooToImplement(yourAClass) however. To prevent this you could create a class that provides the information that fooToImplement() needs, but that can only be instanciated from within AClass:
interface FooImplementation {
void fooToImplement(AClass.AClassFooView a);
}
public abstract class AClass {
private final FooImplementation fooImpl;
protected AClass(FooImplementation fooImpl) {
this.fooImpl = fooImpl;
}
public class AClassFooView {
...
private AClassFooView() {
}
}
public void foo() {
...
fooImpl.fooToImplement(this.new AClassFooView());
...
}
}
But fooToImplement could pass the reference to AClassFooView to other classes...
However depending on the implementors of your class making absolutely sure in the documentation, that nobody should call fooToImplement() could also be an alternative.
Ultimately you have to trust the implementors, since there's also the the possibility of someone using reflection to get access to private members, reverse engeneering+changing+recompiling your class ect..
You can use AOP to this, for example add aspect #Before to fooToImplement() and check stacktrace of calling and throw IllegalArgumentException if fooToImplement() be called any method except foo(), something like:
if(!Thread.currentThread().getStackTrace()[1].getMethodName().equals("foo")) {
throw new IllegalArgumentException("You musn't call fooToImplement() directly"+
", using foo() instead");
}
However this way has two problem:
perfomance
runtime exception
Trying to call a static method from an abstract class inside an instanced class. This is a primitive coding example of what I'm trying to do, but not sure how to go about it.
DataSource myDataSource = new DataSource();
DataAdapterTest.initialize(myDataSource);
public abstract class DataAdapterTest extends DataAdapter {
public static void initialize(DataSource d) {
d.addDataAdapter(DataAdapterTest.class);
}
public static void onCreate() {
does something here
}
}
public class DataSource {
public void addDataAdapter(Class<DataAdapter> c) {
c.onCreate();
}
}
Your problem is unclear. I'll answer to what I guess the problem is.
Signature compile error
I guess you have the following compile error:
The method addDataAdapter(Class) in the type
Main.DataSource is not applicable for the arguments
(Class)
Just use a wider signature for addDataAdapter()
public void addDataAdapter(Class<? extends DataAdapter> c) {
onCreate call
You seem to be trying to use polymorphism with static methods, which is not a good idea since static methods are relative to a class.
c.onCreate();
You can't directly call a method from the class this way, because c is a Class object instance, and does not have such a method.
It is not the same as calling:
DataAdapterTest.onCreate();
You should pass an instance of the class instead of a Class object, and use instance methods instead of static methods. On this aspect, it is hard to give advice because we don't know what you're trying to achieve.
Design problem
Needless Class parameter
You commented:
I need the DataSource to be able to call a method of varying
DataAdapter abstract classes
The code you gave here only uses one class extending DataAdapter. If you need several, then put at least 2 in your minimal example.
As of right now, I don't see the need of passing on a class here. You could as well do the following:
DataSource myDataSource = new DataSource();
DataAdapterTest.initialize(myDataSource);
public abstract class DataAdapterTest extends DataAdapter {
public static void initialize(DataSource d) {
d.addDataAdapter();
}
public static void onCreate() {
//does something here
}
}
public class DataSource {
public void addDataAdapter() {
DataAdapterTest.onCreate();
}
}
Needless static stuff
If everything in your DataAdapterTest class is static, then what is the purpose of extending DataAdapter? You can't use any inherited stuff without an instance of your child class.
I have a Java problem with nested classes.
My first class structure looked like this:
public class TopClass {
public void mainMethod() {
// uses the different "method" methods from
// NestedClass-implementing nested classes
}
private interface NestedClass {
public void method();
}
private class NestedClass1 {
public void method() {
}
}
private class NestedClass2 {
public void method(){
}
}
}
But now I want these method() methods to be static because they should be principally.
I cannot make them static without having them in a static class, but that's no problem, I made the classes static, they should be anyway.
It looks like this right now:
public class TopClass {
public void mainMethod() {
// uses the different "method" methods from
// NestedClass-implementing nested classes
}
private static interface NestedClass {
public void method();
}
private static class NestedClass1 {
public static void method() {
}
}
private static class NestedClass2 {
public static void method(){
}
}
}
But then the trouble begins. A static method does not inherit correctly from a non-static interface method, as I get this message This static method cannot hide the instance method from TopClass.NestedClass in Eclipse.
When I make the interface method static, it gives me this error: Illegal modifier for the interface method method; only public & abstract are permitted
So I thought of an abstract class, and tried this:
public class TopClass {
public void mainMethod() {
// uses the different "method" methods from
// NestedClass-implementing nested classes
}
private static abstract class NestedClass {
public static abstract void method();
}
private static class NestedClass1 {
public static void method() {
}
}
private static class NestedClass2 {
public static void method(){
}
}
}
But again, seemingly abstract methods cannot be declared static: The abstract method method in type NestedClass can only set a visibility modifier, one of public or protected.
Leaving the static away (in the abstract class method), errors this on the method methods in the NestedClass1 & 2: This static method cannot hide the instance method from TopClass.NestedClass.
Isn't there any way to declare some kind of superstructure for covering static methods?
EDIT:
The problem I actually try to solve it the lack of possibility of Java for storing references to methods. So instead I have those classes everyone with just one method, but to store them in a List f.e. they must be able to be "caught" by a superstructure.
I got the hint to try anonymous classes or enums, gonna try that now.
Interfaces and statics don't go together. At all. There is no Java support for creating / imposing patterns on static methods.
A static method declaration must always be followed by a definition. It cannot be implemented by subclasses.
I think you're just not approaching your problem right. Try a different approach!
Make NestedClass an interface NestedInterface and store your different implementations as anonymous classes implementing this interface:
public static final NestedInterface firstNested = new NestedInterface() {
#Override
public void method() {
// ...
}
};
Make NestedClass an enumeration NestedEnum and store your different implementations as enumeration values implementing an abstract method from the enumeration. This only works if you have a fixed number of implementations you which to choose from and you do not want to accept NestedClass implementations from outside sources.
public enum NestedEnum {
FIRST {
#Override
public void method() {
// ...
}
};
public abstract void method();
}
EDIT: In reply to your comment:
The classes itself are static as well..
static in the context of a nested class means that this class can be instantiated without an instance of the containing class.
A regular nested class such as in your first example can be instantiated through TopClass.this.new NestedClass1(). Normally you'd simply write new NestedClass1() from within the constructor or an instance method of TopClass, but in this verbose form you can clearly see the dependence on TopClass.this. This can also be seen from any method of NestedClass1, as you have access to the containing class with TopClass.this.
A static nested class such as in your second example can be instantiated through new TopClass.NestedClass1(). Once again, you could just write new NestedClass1() but the verbose form clearly shows that the construction only depends on TopClass and is not associated with an instance of TopClass. You could even create an instance from an outside class using the same snippet new TopClass.NestedClass1() without ever creating a TopClass instance.
I suggest you take a look at this question on inner classes and static nested classes.
The fact the your interface/abstract class is nested is irrelevant to the problem.
You just can't. There is no way in Java to enforce some class to implement static methods. Just cry and surrender and use instance methods.
static abstract is a contradiction. Static methods are not like other languages' class methods. When you make a static method it goes on a single class, it doesn't get inherited by or have its implementation deferred to subclasses.
You don't explain why you want these methods to be static. If you want these methods to be defined by subclasses then they shouldn't be.
I have an interface I that is implemented by a base class B. The base class is extended by a bunch of classes (A,C,D) that must init some of the protected vars declared in base class B. I'd like to make the declaration of a constructor mandatory in the subclasses (A,C,D), to discourage the user from relying on default constructor that's declared in B. Yet I do want the B's default constructor to execute automatically, since B can be used by itself as well. How can I accomplish this?
thanks
Use an abstract superclass of B with a private constructor:
public abstract class BSuper {
private BSuper() {
// initialize stuff
}
protected BSuper(some params) {
this():
// other init with parms
}
}
public class B extends BSuper {
public B(some other params) {
super(some params);
}
}
public class A extends B {
public A() {
super(some other params);
}
}
or similar
Make B's default constructor private and call this(); from within the parameterized constructor...
public class B {
private B() {
super();
}
public B( Foo foo ) {
this();
}
public static B createInstance() {
return new B();
}
}
Edit: Miss read the issue, removed abstract keyword from class declaration. Also added public static factory method for creating B class. It calls B's default constructor.
Just write a comment in the Javadoc that says "Use of default constructor is discouraged when subclassing." In my experience, trying to enforce that programmatically is not worth the effort and could cause problems latter on. Simple English will do.
If class B is going to have its own default constructor, what you want is impossible. When you derive from a class, you're telling the compiler that it should allocate memory for a base class object in every instance of the derived class. There's no way to tell a java compiler to suddenly take away some of the base class's functionality every time that something is inherited from it.
Also note that constructors and static factory methods can't be abstract, so even if B could be an abstract class you would have to do something like:
public class B {
B() {
initialize();
}
protected abstract void initialize();
}
...along with making sure that the derived classes implement default constructors that call super()