Java - Update Object from another class - java

How can I update an object in class A from a method in class B without using the return?
for example:
public class A {
//my main class
private javax.swing.JTextField txtField1;
//a text field (txtField1) is initialized in this class and drawn
}
public class B {
public void doSomething(){
//does something and updates the txtField1 in class A
}
}
and once again, I do not wish to use return since my return is already returning another value from the same method.

There are many ways you could achieve this. The simplest would be to pass the object into the method in class B:
public void doSomething(JTextField fieldToUpdate){
//your logic here
fieldToUpdate.setText("something");
}
Then you can just update fieldToUpdate directly. This is not a great design pattern since it directly exposes control of a variable owned by 1 class to another.
Another alternative is to pass the instance of Class A into the method and call public methods on it:
public void doSomething(A aInstance){
//your logic here
aInstance.setText("something");
}
then in class A you'd need to define
public void setText(String text){
txtField1.setText(text);
}
This is a little better since class B doesn't have direct access to the internals of Class A.
An even more encapsulated response (though probably overkill for a case this simple) is to define an Interface and pass an instance of a class that implements the interface to the method in class B:
public void doSomething(TextDisplayer txt){
//your logic here
txt.setText("something");
}
then in class a:
public class A implements TextDisplayer{
public void setText(String txt){
txtField1.setText(txt);
}
}
then the interface:
public interface TextDisplayer{
public void setText(String txt);
}
The advantage of this approach is that it keeps class B completely decoupled from the class A. All it cares about is that it is passed something that knows how to handle the setText method. Again, in this case it is probably overkill, but it is the approach that keeps your classes as decoupled as possible.

You either need to call a method in class A, or make the text field static (bad idea).
Depending on usage, class A could instantiate a B as a swing worker/etc. and give B the specific information it needs. It could also be the other way around, B instantiates an `A.

assume you have a public setter method in A to change the value of txtField1. (because the property you want to change has keyword "private")
say in A, you have
public void setTxtField1Value(String newValue){
this.txtField1.value=newValue; // using the right method in api. I am not familiar with gui..
}
then in B, the method would be:
public class B {
public void doSomething(A a){
//does something and updates the txtField1 in class A
a.setTxtField1Value("foobar");
}
}

Related

How do i ensure implementation of a public static function with interface

Since Java 8, we are able to define static and default methods in interface. But I need to ensure a public static method say foo() to be implemented in all the classes that implements a particular interface say interface A. How do I do that , or is it at all possible ?
The interface A:
package com.practice.misc.interfacetest;
public interface A {
public static Object foo(); //Eclipse shows error : 'This method requires a body instead of a semicolon'
String normalFunc();
}
Class B :
package com.practice.misc.interfacetest;
public class B implements A{
#Override
public String normalFunc() {
return "B.normalFunc";
}
//I need to ensure that I have to define function foo() too
}
Class C :
package com.practice.misc.interfacetest;
public class C implements A{
#Override
public String normalFunc() {
return "C.normalFunc";
}
//I need to ensure that I have to define function foo() too
}
Edit 1:
Actual case :
I have one public static method getInstance() (returning Singleton instance of that class) in all the implementing classes, and I want to ensure all the future classes other developers write must have that static method implemented in their classes. I can simply use reflection to return that instance by calling the getInstance() method from a static method of the interface, but I wanted to make sure that everyone implements the getInstance() in all the implementing classes.
static methods from interface are not inherited (1). They are inherited in case of a class, but you can not override them (2); thus what you are trying to do is literally impossible.
If you want all classes to implement your method, why not simply make it abstract (and implicitly public) to begin with, so that everyone is forced to implement it.
Eugene already pointed out that static methods can not be overridden. I suggest that you extract the singleton behavior to a separate interface. For example:
public interface A {
String normalFunc();
}
public class B implements A {
#Override
public String normalFunc() {
return "B.normalFunc";
}
// TODO add getInstance for singleton
}
public interface Singleton {
// TODO extensive javadoc to describe expected singleton behavior
A getInstance();
}
public class BSingleton implements Singleton {
#Override
public A getInstance() {
return B.getInstance();
}
}
Finally you can use any object of type BSingleton to get the singleton object of B.

How to use methods from extended class on objects from main class? [JAVA]

I'm starting with developing something, and I have few classes that are using the same methods, so I want to have it in one class (to easy fixing in one place etc). Problem is that I dont know how to use methods from different classes on object in main class. Code for explanation:
public class A extends C {
public UiDevice device;
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
public void test(){
methodFromC();
}
}
public class B extends C {
public UiDevice device;
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
public void test(){
methodFromC();
}
}
public class C {
protected void methodFromC(){
device.something();
}
}
I know that I can do it by adding argument to methodFromC:
public class C {
protected void methodFromC(UiDevice device){
device.something();
}
and running it by
methodFromC(device);
But maybe is there better solution?
First of all, as a beginning programmer unless you are doing it for school, avoid extending classes. It ends up a big spaghetti mess until you learn to moderate it (I fell for this one big-time), What you are trying to do isn't good code right now.
I THINK what you are trying to do, however is something like this:
(Assume unspecified code remains pretty much as it is)
class A extends C
{
public UiDevice getDevice()
{
return device;
}
}
abstract class C
{
public abstract UiDevice getDevice();
public methodFromC()
{
getDevice().doSomethingToDevice();
}
}
This pattern allows you to access something from A in a parent class.
B can also have it's own device. I believe this is what you are after (C being able to operate on A's device or B's device depending on which one extended C).
Get rid of the public variable.
You can use the super keyword to access anything from the class you are extending. In your case :
public class B extends C {
public UiDevice device;
device = super.methodFromB();
public void test(){
methodFromB();
}
}
If many of your classes declare methods that do the same thing, you can make them inherit from one class, let's call it class A. In class declare and implement the method. Then in child classes declare methods and in their body write:
super.nameOfYourMethodFromParentClass();
In general, to use a method from different class you just create an object of the class and call a method on it. Like:
class A {
public void myMethod() {
B b = new B();
b.methodFromB();
}
}
When it comes to inheritance be aware of this:
You can create an object of a class that declares this method or of a class that inherits from the class that declares this method and call the method on this object.
Like:
Class A inherits from C. In class C you have method methodFromC() declared. To invoke method from class C on object from class A you can do:
A a = new A();
a.methodFromC(device);
The invoked method here is the method from class C.
But if in class A you override method from class C (that means in class A you declare a method that has the same name and parameters as method in class C), then by executing the code I have written above you will invoke the method from class A, not class C.

Can an overriding method have a different access specifier from that in the base class?

Which access modifier, in an abstract class, do I have to use for a method,
so the subclasses can decide whether it should be public or not? Is it possible to "override" a modifier in Java or not?
public abstract class A {
??? void method();
}
public class B extends A {
#Override
public void method(){
// TODO
}
}
public class C extends B {
#Override
private void method(){
// TODO
}
}
I know that there will be a problem with static binding, if
someone calls:
// Will work
A foo = new B()
foo.method();
// Compiler ?
A foo = new C();
foo.method();
But maybe there is another way. How I can achieve that?
It is possible to relax the restriction, but not to make it more restrictive:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method(){ // OK
}
}
public class C extends A {
#Override
private void method(){ // not allowed
}
}
Making the original method private won't work either, since such method isn't visible in subclasses and therefore cannot be overriden.
I would recommend using interfaces to selectively expose or hide the method:
public interface WithMethod {
// other methods
void method();
}
public interface WithoutMethod {
// other methods
// no 'method()'
}
public abstract class A {
protected void method();
}
public class B extends A implements WithMethod {
#Override
public void method(){
//TODO
}
}
public class C extends B implements WithoutMethod {
// no 'method()'
}
... then only work with the instances through the interfaces.
When overriding methods, you can only change the modifier to a wider one, not vice versa. For example this code would be valid:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method() { }
}
However, if you try to narrow down the visibility, you'd get a compile-time error:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
private void method() {}
}
For your case, I'd suggest to make C not implementing A, as A's abstraction implies that there's a non-private method():
public class C {
private void method(){
//TODO
}
}
Another option is to make the method() implementation in C throwing a RuntimeException:
public class C extends A {
#Override
public void method(){
throw new UnsupportedOperationException("C doesn't support callbacks to method()");
}
}
What you are asking for is not possible for very good reasons.
The Liskov substitution principle basically says: a class S is a subclass of another class T only then, when you can replace any occurrence of some "T object" with some "S object" - without noticing.
If you would allow that S is reducing a public method to private, then you can't do that any more. Because all of a sudden, that method that could be called while using some T ... isn't available any more to be called on S.
Long story short: inheritance is not something that simply falls out of the sky. It is a property of classes that you as the programmer are responsible for. In other words: inheritance means more than just writing down "class S extends T" in your source code!
This is impossible because of the polymorphism. Consider the following. You have the method in class A with some access modifier which is not private. Why not private? Because if it was private, then no other class could even know of its existence. So it has to be something else, and that something else must be accessible from somewhere.
Now let's suppose that you pass an instance of class C to somewhere. But you upcast it to A beforehand, and so you end up having this code somewhere:
void somewhereMethod(A instance) {
instance.method(); // Ouch! Calling a private method on class C.
}
One nice example how this got broken is QSaveFile in Qt. Unlike Java, C++ actually allows to lower access privileges. So they did just that, forbidding the close() method. What they ended up with is a QIODevice subclass that is not really a QIODevice any more. If you pass a pointer to QSaveFile to some method accepting QIODevice*, they can still call close() because it's public in QIODevice. They “fixed” this by making QSaveFile::close() (which is private) call abort(), so if you do something like that, your program immediately crashes. Not a very nice “solution”, but there is no better one. And it's just an example of bad OO design. That's why Java doesn't allow it.
Edit
Not that I missed that your class is abstract, but I also missed the fact that B extends C, not A. This way what you want to do is completely impossible. If the method is public in B, it will be public in all subclasses too. The only thing you can do is document that it shouldn't be called and maybe override it to throw UnsupportedOperationException. But that would lead to the same problems as with QSaveFile. Remember that users of your class may not even know that it's an instance of C so they won't even have a chance to read its documentation.
Overall it's just a very bad idea OO-wise. Perhaps you should ask another question about the exact problem you're trying to solve with this hierarchy, and maybe you'll get some decent advises on how to do it properly.
Here is a part of the #Override contract.
The answer is : there isn't any possibility to achieve what you have.
The access level cannot be more restrictive than the overridden
method's access level. For example: if the superclass method is
declared public then the overridding method in the sub class cannot be
either private or protected.
This is not a problem concerning abstract classes only but all classes and methods.
THEORY:
You have the determined modifiers order:
public <- protected <- default-access X<- private
When you override the method, you can increase, but not decrease the modifier level. For example,
public -> []
protected -> [public]
default-access -> [public, default-access]
private -> []
PRACTICE:
In your case, you cannot turn ??? into some modifier, because private is the lowest modifier and private class members are not inherited.

Creating Innerclass with full access to local variables of outerclass

So here's the scenario.
I have a class A, and I want some of its methods to behave differently depending on how the class is called.
What I've done now is something like this:
interface Interface{
public void someMethod();
}
class A{
int variable;
Interface getA1(){
return new A1();
}
Interface getA2(){
return new A2();
}
class A1 extends A implements Interface{
public void someMethod(){
variable++;
}
}
class A2 extends A implements Interface{
public void someMethod(){
variable--;
}
}
}
Now the problem with this is that when getA1() or getA2() is called, it will actually return a completely new instance of A1, or A2, where the int variable is totally separate to the parent class A (duh, silly me of course thats how it works).
So the question is. Is it possible in java to return some kind of inner class that allows you to modify the data within the outer class through it's methods?
The key thing is having a single class that can return interfaces that modify that single class in different ways, depending on which method was used to create that interface.
I might be overlooking something simple here, sorry but it's got me stumped! :(
Edit: I think the better way of explaining it is - I want to give direct access to local variables, to a subclass (or another class), and have a method in the original class that can create the other class.
EDIT2: The reason why it created a separate instance when getA1()/getA2(), is likely because class A1 and A2 were declared to extend A. It seems like if the extends clause is removed, then it works as expected.
Yes an anonymous class would do e.g.
interface Interface{
public void someMethod();
}
public class A {
int variable;
Interface getA1() {
return new Interface() {
#Override
public void someMethod() {
variable++;
}
};
}
}
It should be pointed out though that this is equivalent to declaring non-static inner classes albeit more concise.
First of all, I find it very strange that your inner classes are extending the outer class. I can't think of a good reason to do that and I'm not exactly sure what that even does.
Besides that, I don't understand your issue. All inner classes have access to their parent class's fields. For example, the following:
public class Tester {
private int myInt;
public InnerTester getInnerTester() {
return new MyInnerTester();
}
public InnerTester getOtherInnerTester() {
return new OtherInnerTester();
}
public interface InnerTester {
public void doStuff();
}
public class MyInnerTester implements InnerTester{
#Override
public void doStuff() {
myInt++;
}
}
public class MyOtherInnerTester implements InnerTester {
#Override
public void doStuff() {
myInt++;
}
}
public static void main(String[] args) {
Tester tester = new Tester();
System.out.println("Before: " + tester.myInt);
tester.getInnerTester().doStuff();
tester.getOtherInnerTester().doStuff();
System.out.println("After: " + tester.myInt);
}
}
outputs:
Before: 0
After: 2
However, this all seems pretty shady. I'm not exactly sure why you would want to take advantage of this behavior. I've done similar things with action listeners before, but I wouldn't exactly call their parent object an "ActionListenerFactory". Why don't you just have a method to increment the field on the object itself?

Why can't java find my method?

I am trying to wrap my mind around something in java. When I pass an object to another class' method, can I not just call any methods inherent to that object class?
What is the reason code such as the example below does not compile?
Thank you,
class a {
public static void myMethod(Object myObj) {
myObj.testing();
}
}
class b {
public void testing() {
System.out.println ("TESTING!!!");
}
}
class c {
public static void main (String[] args) {
b myB = new b();
a.myMethod(myB);
}
}
Edit: The reason I have left the parameter in myMethod as type Object, is because I would like to be able to pass in a variety of object types, each having a testing() method.
If you would like to pass in a variety of objects with testing() methods, have each object implement a Testable interface:
public interface Testable
{
public void testing()
}
Then have myMethod() take a Testable.
public static void myMethod(Testable testable)
{
testable.testing();
}
Edit: To clarify, implementing an interface means that the class is guaranteed to have the method, but the method can do whatever it wants. So I could have two classes whose testing() methods do different things.
public class AClass implements Testable
{
public void testing()
{
System.out.println("Hello world");
}
}
public class BClass implements Testable
{
public void testing()
{
System.out.println("Hello underworld");
}
}
The problem is that myMethod can't know it's getting a b object until it actually runs. You could pass a String in, for all it knows.
Change it to
public static void myMethod(b myObj) {
myObj.testing();
}
and it should work.
Update of the question:
Edit: The reason I have left the parameter in myMethod as type Object, is because I would like to be able to pass in a variety of object types, each having a testing() method.
As Amanda S and several others have said, this is a perfect case for an interface. The way to do this is to create an interface which defines the testing() method and change myMethod to take objects implementing that interface.
An alternative solution (without interfaces) would be to reflectively discover if the object has a testing() method and call it, but this is not recommended and not needed for a such a simple case.
What you are talking about is duck typing. Java doesn't have duck typing.
Therefore you need to define an interface that all the classes with a testing() method implement.
e.g:
public interface Testable
{
public void testing()
}
class B implements Testable
{
public void testing() {
System.out.println ("TESTING!!!");
}
}
class A {
public static void myMethod(Testable myObj) {
myObj.testing();
}
}
Your issue is a classic argument in favor of an interface. You want as generic as possible, yet you want every object you pass to have a testing() method. I suggest something along the lines of the following:
public interface Testable
{
public void testing();
}
public class A
{
public static void myMethod(Testable myObj)
{
myObj.testing();
}
}
public class B implements Testable
{
public void testing()
{
System.out.println("This is class B");
}
}
public class C implements Testable
{
public void testing()
{
System.out.println("This is class C");
}
}
public class Test
{
public static void main (String[] args)
{
B myB = new B();
C myC = new C();
A.myMethod(myB); // "This is class B"
A.myMethod(myC); // "This is class C"
}
}
Because you're passing in an Object (b inherit from Object). Object doesn't have testing, b does.
You can either pass in b or cast the object to b before calling the method.
EDIT
To pass in a generic class that implements that method: you'll want to make an interface that has the method signature and pass in the interface type instead of Object. All objects that you pass in must implement the interface.
You can only access the members that are visible for the type of reference you have to the object.
In the case of myMethod(Object myObj) that means only the members defined in Object, so in class a the members of class b will not be visible.
If you changed the definition of a.myMethod to be public static void myMethod(b myObj) you would then be able to see the testing method on the instance of b while in myMethod.
update based on clarification:
In that case defining an interface for all of them to implement is likely what you want.
public interface Testable {
public void testing();
}
public class a {
public static void myMethod(Testable myObj) {
myObj.testing();
}
}
public class b implements Testable {
public void testing () {
System.out.println("TESTING!!!");
}
}
Why can’t java find my method?
Because of the way Java was designed.
Java is "statically typed" that means objects types are checked during compilation.
In Java you can invoke a method only if that method belongs to that type.
Since this verification is made during compilation and the Object type does not have the "testing()" method, the compilation fails ( even though if at runtime the objects do have that method". This is primarily for safety.
The workaround as described by others will require you to create a new type, where you can tell the compiler
"Hey, the instances of this type will respond the the testing method"
If you want to pass a variety of objects and keep it very generic, one way is having those objects to implement and interface.
public interface Testable {
public void testing();
}
class A implements Testable { // here this class commits to respond to "testing" message
public void testing() {
}
}
class B implements Testable { // B "is" testable
public void testing() {
System.out.println("Testing from b");
}
}
class C implements Testable { // C is... etc.
public void testing() {
//....
}
}
Later somewhere else
public void doTest( Testable object ) {
object.testing();
}
doTest( new A() );
doTest( new B() );
doTest( new C() );
The "OTHER" way to do this, in java is invoking the methods reflectively, but I'm not sure if that's what you need, for the code is much more abstract when you do it that way, but that's how automated testing frameworks (and a lot of other frameworks such as Hibernate) do actually work.
I hope this help you to clarify the reason.
If you REALLY, REALLY want to keep the parameter as abstract as possible, you should consider reflection API. That way, you can pass whatever object you want and dynamically execute the method you want. You can take a look at some examples.
It's not the only way, but it might be a valid alternative depending on your problem.
Keep in mind that reflection is way slower than calling your methods directly. You might consider using an interface as well, such as the one on Amanda's post.

Categories

Resources