I'm having several problems with the following code:
private ArrayList<TemperatureSensor> sensors = new ArrayList<TemperatureSensor>();
//[...]
private double getAverageTemperature() {
double addition = 0;
for(TemperatureSensor sensor : this.sensors)
addition += sensor.getTemperature();
return addition / this.sensors.size();
}
}
The method getTemperature is in the class TemperatureSensor, and it's defined as this:
public int getTemperature() {
// random number [5,40]
return new Random(System.currentTimeMillis()).nextInt(36)+5;
}
In the getAverageTemperature() method I'm getting an error saying that "The method getTemperature() is undefined for the type TemperatureSensor"
Also, how do I call a specific method that two classes have, and their objects are stored in an ArrayList, from an abstract class?
Thanks in advance.
The code looks ok. Does everything compile? Is everything freshly compiled? From what you describe I'd assume there is an old version of the class on your classpath that does not yet have that method.
Clean and compile you code once again as code looks fine. For your second question, find example below
public abstract class A {
public abstract void method();
}
public class B extends A{
public void method(){
//code
}
}
public class C extends A {
public void method(){
//code
}
}
public class Main{
public static void main(String args[]){
ArrayList<A> obj=new ArrayList<A>();
obj.add(new B());
obj.add(new C());
for (A a : obj) {
a.method(); // it will call respective method of B and C class
}
}
}
Related
I'm studying for a Java-exam and have a question concerning static and dynamic types.
I've got 4 classes: A, B, C and Main.
public class A {
private void tell(){
System.out.println("AA");
}
}
public class B extends A {
public void tell(){
System.out.println("BB");
}
}
public class C extends B {
}
public class Main{
public static void main(String[] args) {
A c = new C();
c.tell();
}
}
My suggestion was: the output should be "BB", because c has the dynamic type C. Since C doesn't have the method "tell" the method of the upper class B is used, which prints "BB".
The outcome however is an error, because Java looks for "tell" in A. In A it of course can't find it, because there it is declared priavte. But why does it look in A, although only it's static type is A, but it's dynamic type is C?
You are getting an error because at compile time, the compiler does not know the actual instance that will be put in A, so when the compiler sees c.tell() he only looks at the class A which indeed does not have an acessible tell() method.
One way to understand this is with this example:
public class A {
private void tell(){
System.out.println("AA");
}
}
public class B extends A {
public void tell(){
System.out.println("BB");
}
}
public class C extends A {
}
public class Main{
public static void main(String[] args) {
A b = new B();
b.tell();
A c = new C();
c.tell();
}
}
You can see that the first 2 lines would be ok (by your current logic of thinking). B has the method tell() so b should be able to call tell(). But using the exact same assignment with another subclass of C which does not have the tell() method then your logic would fail. A nor C have the tell() method so the program suddenly has a call to a method that does not exist or is not accessible.
My code is similar to this:
class Base{
public void handleObject(A a){
//more code...
System.out.println("A");
}
}
class Sub extends Base{
public void handleObject(B b){
//more code specific to this instance and class B
System.out.println("B");
}
public void handleObject(C c){
//more code specific to this instance and class C
System.out.println("C");
}
}
Where B and C inherit from A.
I then want to call handleObject of Base from this code:
//...
Sub s = new Sub();
A[] obj = {new B(), new B(),new C(), new A()};
for(A o:obj){
s.handleObject(o);
}
//...
And I expect Sub.handleObject(B b) to be called for each object of type B, Sub.handleObject(C c) for type C, and Base.handleObject(A a) to be called for objects of type A.
The real result is it prints "A" three times.
Is it possible to make it work using java's overloading capabilities or must I type check every object myself? If not, what is the best practice to achieve the desired behavior?
This question is very similar to mine but the answers only show why his attempts did not work and did not offer a sufficient solution for me.
I have also tried making it work using Visitor Pattern, but in their example it seems like it is required for the Base class (or at least the interface) to know about Sub, which is something I prefer not to have my project.
I suggest you use polymorphism to your advantage. Instead of trying to figure out how to behave for different classes of objects, let each class provide its own behavior:
class A {
public void handleMyself() {
System.out.println("A");
}
}
class B extends A {
#Override
public void handleMyself() {
System.out.println("B");
}
}
class C extends A {
#Override
public void handleMyself() {
System.out.println("C");
}
}
class Base {
public void handleObject(A a) {
a.handleMyself();
}
}
class Sub extends Base {
public static void main(String... args) {
Sub s = new Sub();
A[] obj = {new B(), new B(), new C(), new A()};
for (A o : obj) {
s.handleObject(o);
}
}
}
Let's say I have three Classes A,B,C.
All three do the same thing, but in a different way, they differ in efficiency.
All the method names, variable names inside the three classes are same.
class A{
public static int method(){
......
return result;
}
}
class B{
public static method(){
......
return result;
}
}
class C{
public static method(){
......
return result;
}
}
I have test class, which has a method to test the code in the above three classes. Since this testMethod() is common to all the three classes, is there a way to call this method with objects of classes A,B,C ?
class Test{
public static int testMethod(Object ABC)
{
return ABC.method();
}
public static void main(String[] args){
A a = new A();
SOP(testMethod(a));
B b = new B();
SOP(testMethod(b));
C c = new C();
SOP(testMethod(c));
}
}
The only approach I can think of is creating three different methods for each of the classes, like this.
class Test{
public static int testMethodA(A a)
{
return a.method();
}
public static int testMethodB(B b)
{
return b.method();
}
public static int testMethodC(C c)
{
return c.method();
}
public main()
{
//call to each of the three methods
............
}
What is the best approach to this scenario? Basically I want to have only one method that can test all three classes.
Create an interface with the common method for all classes. Then, make each class implement this interface. In your test code, use the interface as parameter type and pass an instance of each class to the method. Note that when you do this, the method to test should not be static.
In code:
public interface MyInterface {
//automatically public
int method();
}
public class A implements MyInterface {
#Override //important
//not static
public int method() {
/* your implementation goes here*/
return ...;
}
}
public class B implements MyInterface {
#Override //important to check method override at compile time
public int method() {
/* your implementation goes here*/
return ...;
}
}
//define any other class...
Then the test:
public class Test {
//using plain naive console app
public static void main(String[] args) {
MyInterface myInterfaceA = new A();
testMethod(myInterfaceA);
MyInterface myInterfaceB = new B();
testMethod(myInterfaceB);
//and more...
}
public static void testMethod(MyInterface myInterface) {
myInterface.method();
}
}
Or if you prefer to use JUnit:
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class MyInterfaceTest {
MyInterface myInterface;
#Test
public void methodUsingAImplementation() {
myInterface = new A();
//code more human-readable and easier to check where the code fails
assertThat(myInterface.method(), equalTo(<expectedValue>));
}
//similar test cases for other implementations
}
I am trying to update a jlabel from another class. I've pasted my code below.
Class A {
public void setNetAmount(String s){
jLabel51.setText(s);
}
public void setDis_percentage(String s){
jLabel53.setText(s);
}
public void setDiscount(String s){
jLabel55.setText(s);
}
public void setAdjustment(String s){
jLabel57.setText(s);
}
}
Class B{
public void SetData(){
new A.setNetAmount(""+netAmount);
new A.setDis_percentage(""+dis_percentage);
new A.setDiscount(""+discount);
new A.setAdjustment(""+adjustment);
}
}
I am calling the SetData() method in Class A.
public void getData(){
B b = new b();
b.setData();
}
Is there anything wrong with my code ? It is not working at all. Is there any issue of EDT? Please help.
You can't keep invoking "new A". This creates a new instance of class A.
Not really sure why you have a class B to invoke a few methods from class A, but if you use this approach then you would need to pass a reference of class A the your class B method.
Something like:
public class B
{
public void setData(A a)
{
a.setAmount(...);
a.setPercentage(...);
...
}
}
Then when you invoke the method in your class A you would use:
B b = new B();
b.setData(this);
Although this is a really strange design.
I'm new to Java, and I've read over some tutorials on overriding methods, but an example I'm looking at isn't working the way I expect. For example, I have the code:
public class A{
public void show(){
System.out.println("A");
}
public void run(){
show();
}
public static void main( String[] arg ) {
new A().run();
}
}
public class B extends A{
#Override
public void show(){
System.out.println("B");
}
}
When I instantiate and call B.run(), I would expect to see "B" outputted. However, I see "A" instead. What am I doing wrong?
Edit: Yes, the classes are in two separate files. They're shown together for brevity.
Edit: I'm not sure how B is being instantiated, as it's being done by a third-party program using a classloader.
Edit: More info on the third-party program. It starts by calling A.main(), which I didn't initially show (sorry). I'm assuming I need to make "new A().run();" more generic to use the name of the current class. Is that possible?
That code will output B if you:
(new B()).run();
Whatever the problem is, it's not in the code you've quoted.
Updated (after your edit)
If the third-party program is calling A.main(), there's nothing (reasonable) you can do in B that will inject itself into A. As long as A.main is doing new A().run(), it's going to have an instance of A, not an instance of B. There's no "current class name" to use, or if there is (depends on your point of view), it's A, not B.
You'll have to get the third-party program to call B in some way, rather than A, or just modify A directly (e.g., getting rid of B entirely). You do not want to modify A to make it use B; that tightly binds it to a descendant and makes the separation between them largely pointless.
Hope that helps.
I tried, putting your two classes in two files, and it worked nicely, outputting "B". I called :
B b = new B();
b.run();
UPDATED : Also works as (because it is the same runtime instance):
A a = new B();
a.run();
Works for me.
Here's my code for A and B:
package so;
public class A{
public void show(){
System.out.println("A");
}
public void run(){
show();
}
}
class B extends A{
#Override
public void show(){
System.out.println("B");
}
}
Here's my entry point:
package so;
public class EntryPoint {
public static void main(String[] args) {
B b = new B();
b.run();
}
}
It prints out 'B'.
It depends of instantiating. Try this:
A v1 = new A();
A v2 = new B();
B v3 = new A();
B v4 = new B();
v1.run()
v2.run()
v3.run()
v4.run()
I tried your example and my output was B.
How are you instantiating? Here's the exact code I ran.
public class Test {
public static class A {
public void show() {
System.out.println("A");
}
public void run() {
show();
}
}
public static class B extends A {
#Override
public void show() {
System.out.println("B");
}
}
public static void main(String args[]) {
A a = new B();
a.run();
}
}
If your external program instantiates A, you will have A, not B.
But you can try something like this, using some reflection, and pass "com.mypackage.A" or "com.mypackage.B" as arguments to your program.
With this code (exception catch missing), you will be able to print "A" or "B" depending on the string parameter that you pass.
public static void main( String[] arg ) {
String className = arg[0];
Class myClass = Class.forName(className);
Constructor cons = myClass.getConstructor(new Class[0]);
A myObject = (A) cons.newInstance(new Object[0]);
myObject.show();
}