Im newbie in Java and im learning it.
Right now i have two class, i already called class B on class A constructor
class A
public A {
init();
B bb = new B(textField);
bb.doSomething();
}
void init() {
textField = new JTextField();
}
void fly() {
//can i just use bb.doFly();
}
private JTextField textField;
}
My question is, do i have to initialized B bb = new B(); on every single function i want to use on A ?
Question Edited
Its all about scope. If your attribute is at class level, then no you do not have to create a new one each time.
If the attribute is only created within a method scope, then yes you do.
The difference is
class A {
public A() {
// this is at method level scope. It is define INSIDE a method
B bb = new B();
}
}
class level scope is
class A {
// this is at class level scope. It is define OUTSIDE a method
B bb = new B();
public A() {
}
}
No, just refer to the identifier bb:
public class A {
private B bb = new B;
public A() {
}
public void foo() {
bb.printHello(); // you can only call methods on bb which class B supplies
bb.fly(); // won't work; you can only call fly() on objects of type A
}
public void bar() {
bb.printWorld();
}
public void fly() {
System.out.println("I'm flying...");
}
}
public class B {
public B() {
}
public printHello() {
System.out.println("Hello");
}
public printWorld() {
System.out.println("Hello");
}
}
Just a note: Please declare all your attributes private unless you have a good reason to not to.
class A
B bb;
public A {
bb = new B();
bb.doSomething();
}
void fly() {
bb.something()
}
}
No. Suppose you have this code this code:
public class NameOfProgram
{
public static void main(String[] args)
{
A aa = new A();
aa.fly();
}
}
Then the variable bb inside aa is created with the statement new A(). So, you don't have to create an B object and set it to bb as it already exists.
Also, you need to declare the variable outside the constructor or you will not be able to use it in other methods, like fly. To correct it you could do this:
public class A
{
B bb; <-----------------
public A()
{
bb = new B(NameOfVariableIForgotAbout);
}
public void fly()
{
bb.doFly() //Now this should work
}
}
you can also but the B bb; after the method, I just prefer it this way.
Also, your class A has a few errors (so you note for future reference). Firstly, if you want to be able to call a method from an instance of the class (A aa = new A(); aa.fly()) then you need to make the methods public like so:
public void fly()
{
//Insert code here
}
Also , you declared the constructor wrongly. Here is how you did it:
public A
{
//Insert code here
}
and it is done like this:
public A()
{
//Insert code here
}
The first error will cause a compile-time error if you make the call aa.fly() because it is neither private nor public.
The second will cause a compile-time error even if you make no call to the method.
Related
I'm trying to create some system with inner class. My code can be summarized to something like this.
public abstract class A {
public abstract void doSomething();
}
public class B {
public final ArrayList<A> list=new ArrayList<A>();
public B(){
}
}
public class C {
private int i;
public C(B b){
b.list.add(new A(){
public void doSomething(){
i++;
}
});
b.list.add(new A(){
public void doSomething(){
System.out.println(i);
}
});
}
}
public static void main (String[] arg) {
B manager=new B();
new C(manager);
new C(manager);
new C(manager);
}
A is abstract class that will be inherited as inner class (in my original code it is listener class), B is some kind of manager class that hold list of As, and C hold data it's data should be only modified or read by it's inner class and upon initialization it add A to the class B. Code itself works fine. But problem is as there will be various kinds of C something like C2, C3 that does different thing and this leads to my code overwhelmed with thousands of unassigned object new C(manager); this make debugging extra hard and code looks really ugly. So it seems to me my approach in the first place was wrong but have no idea how to avoid this. So how should I change my approach to not have thousands of unassigned objects?
My suggestion is: try not to use constructors to do operations that depend on state (i). Use static functions, and save the state in a separate class (we call it a “context”).
import java.util.ArrayList;
public class Demo {
// A
abstract static class InnerListener {
public abstract void onEvent();
}
// B
static class ListenerManager {
public final ArrayList<InnerListener> listeners = new ArrayList<InnerListener>();
}
static class SideEffectContext {
public int i = 0;
}
// C
static class ListenerUtil {
public static void setupListeners(ListenerManager manager, SideEffectContext context) {
manager.listeners.add(new InnerListener() {
public void onEvent() {
context.i++;
}
});
manager.listeners.add(new InnerListener() {
public void onEvent() {
System.out.println(context.i);
}
});
}
}
public static void main(String[] arg) {
var manager = new ListenerManager();
var ctxA = new SideEffectContext();
var ctxShared = new SideEffectContext();
ListenerUtil.setupListeners(manager, ctxA);
ListenerUtil.setupListeners(manager, ctxShared);
ListenerUtil.setupListeners(manager, ctxShared);
}
}
I have created 3 classes, one superclass "a" and under a two subclasses "b" and "c". I am creating an instance of c, give it an integer "n" and then use subclass b to do some calculation. The problem I am having is that when I create an instance c to call b, the data technically belong to the superclass a/c right? so when i create an instance of b with
b b_instance = new b();
inside the instance of c,
the b calc() function I call would return 0. I guess it's because b has it's own eco-sphere of data?
How do I do this?
2)
Also, how do i call the superclass function of the same name?
Thanks!
public class prog
{
public static void main(String args[])
{
c c1 = new c();
c1.run();
}
}
class a
{
private int number;
void set_number(int n)
{
number = n;
}
int get_number()
{
return number;
}
int calc()
{
return number*2;
}
}
class b extends a
{
int calc()
{
// calling the superclass function calc, then subtract
return super.calc() - get_number();
}
}
class c extends a
{
void run()
{
set_number(1);
b b1 = new b();
System.out.println(b1.calc());
}
}
infinite loop problem
public class prog
{
public static void main(String args[])
{
c c1 = new c();
c1.run();
}
}
class a
{
void calc_a()
{
System.out.println("") ;
}
void calc_b()
{
calc_a(); // meaning the calc_a() in the superclass
}
}
class b extends a
{
void calc_a()
{
super.calc_b();
}
}
class c extends a
{
void run()
{
b b1 = new b();
b1.calc_b();
}
}
b b_instance = new b();
inside the instance of c, the b calc() function I call would return 0.
I guess it's because b has it's own eco-sphere of data?
How do I do this?
A "couple" of possible ways. I'd consider extending c from b, this way c gets all the functionality of a and b, something like...
class c extends b {
void run() {
set_number(1);
System.out.println(calc());
}
}
IF, however, this is not feasible (for some reason or other), then you need to pass the value that c has to b, something like...
class c extends a {
void run() {
set_number(1);
b b1 = new b();
b1.set_number(get_number());
System.out.println(b1.calc());
}
}
Now, having said that, this "smells" to me. What's the point of extending from a just so c can perform b? It would set off alarm bells to me.
The problem is, if your call c#calc, it's just going to a's calc method ... which, based on run, doesn't seem to be what you want to achieve, so it's all just a big mess
2)
Also, how do i call the superclass function of the same name?
Because calling calc directly would cause a StackOverflowError because you're constantly calling yourself.
In this case, you're taking the operation that a is doing and making a modification to it. This is a common practice in OO languages.
Side notes...
Java (and the Java community) already have a well defined set of coding practices. You should take the time to learn them, it will make your code easier to read and make it easier for you to read other peoples codes.
Start with Code Conventions for the Java TM Programming Language
Class names should start with a capital letter and methods are in camelCase, for example...
class A {
private int number;
void setNumber(int n) {
number = n;
}
int getNumber() {
return number;
}
int calc() {
return number * 2;
}
}
Updated...
class a {
void calc_a() {
System.out.println("");
}
void calc_b() {
calc_a(); // meaning the calc_a() in the superclass
}
}
class b extends a {
void calc_a() {
super.calc_b();
}
}
class c extends a {
void run() {
b b1 = new b();
b1.calc_b();
}
}
The question you need to ask yourself is, why does b need to override calc_a? Why not override calc_b? It would solve the issue
how do i override it?
class b extends a {
//void calc_a() {
// super.calc_b();
//}
#Override
void calc_b() {
super.calc_b();
}
}
So, I want to be able to get an instance of a subclass that is being run when it calls a method from the super class. For example, if I had this class:
public class A {
public void aMethod() {
//Here is where I want to see if class B is calling the code
}
}
public class B extends A {
}
public class C {
B b = new B();
b.aMethod();
}
And, like the comment says, I want to check, in aMethod, if class B, the subclass of class A, is calling the code.
As has been pointed out to you, there is almost never a good reason to do this and I agree that you should be using polymorphism instead. However, if you "need" to do this or just want to know how to go about doing something like this, you can use instanceof on this inside of the method:
class A {
public void aMethod() {
if (this instanceof B) {
System.out.println("I'm a B!");
}
}
}
public class B extends A {
public static void main(String[] args) {
B b = new B();
b.aMethod();
}
}
public class A {
public void aMethod() {
if(this.getClass() == B.class){
System.out.println("huhuhuuuuuuuuuuuuuuuuu");
}
}
}
public class B extends A {
}
public class C {
public static void main(String[] args) {
B b = new B();
b.aMethod();
}
}
Check here: How to get the caller class in Java
The 2nd part of the answer from #dystroy is probably a start.
Note that this finds a call at any depth:
for(final StackTraceElement element : Thread.currentThread().getStackTrace()) {
if (element.getClassName().equals(B.class.getName())) {
System.out.println("BINGO");
}
}
If you want to check only a limited depth, don't iterate through all of the array.
This can be useful e.g. if some framework forces you to have a special method or a no-arg constructor to be present, but you don't want any developer to call this method directly. (Yes, it is a hack, but sometimes odd frameworks force you to do odd things). Then you can have an assertion in the unwanted method that just throws an exception if it is called by the wrong corner of your code.
Anyway you should try do avoid things like this if possible.
Consider following situation. I want to achieve the different behavior for methoddA() of class A depending upon from where it is getting call like here from class D or class C. How this can be achieved, method overriding is not working here.
class A
{
public methodA(){ //some code }
}
class B
{
A a = new A()
public methodB()
{
a.methodA();
}
}
class C
{
B b = new B();
public methodC()
{
b.methodB();
}
}
class D
{
B b = new B();
public methodD()
{
b.methodB();
}
}
What you need here is Polymorphism. First create an interface -
public interface MyInterface
{
void methodA();
}
then create two different implementations for two different behaviors -
public class First implements MyInterface
{
public void methodA() {
// first behavior
}
}
public class Second implements MyInterface
{
public void methodA() {
// second behavior
}
}
Now create your other classes as follows -
class B
{
public void methodB(MyInterface m)
{
m.methodA();
}
}
class C
{
B b = new B();
public void methodC()
{
// Pass the corresponding behavior implementation
// as argument here.
b.methodB(new First());
}
}
class D
{
B b = new B();
public void methodD()
{
// Pass the second behavior implementation.
b.methodB(new Second());
}
}
This will result in a more maintainable code.
You can pass the class name to your method as a String and in your method check
if(className.equals("A") // or use isInstanceOf() if you are passing objects of A/B
//do something
if(className.equals("B")
// do something else.
Why do you need two different implementations?
This easy trick can work for you... Please correct me if i am wrong..
I following code I have modified the method signature of Class A1 and Class B1 to accept Object and similarly while calling the methods from Class C and Class D whereever we are calling this method of class B1 pass this as reference. In Class A1 we can then check instanceof object and identify the calling class.
class A1
{
public void methodA(Object c){ //some code }
if (D.class.isInstance(c)){
System.out.println("Called from Class D");
}else if (C.class.isInstance(c)){
System.out.println("Called from Class c");
}else{
System.out.println("Called from Some diff class");
}
}
}
class B1
{
A1 a = new A1();
public void methodB(Object c)
{
a.methodA(c);
}
}
class C
{
B1 b = new B1();
public void methodC()
{
b.methodB(this);
}
}
class D
{
B1 b = new B1();
public void methodD()
{
b.methodB(this);
}
}
public class Testnew{
public static void main(String args[]){
D d = new D();
d.methodD();
C c = new C();
c.methodC();
B1 b = new B1();
b.methodB(b);
}
}
i'm relativly new to java and experimantating a bit with javafx
i want to change a variable from class A while using a method from class B
Main: thats the main class, it contains all the needed stuff(shows the primaryStage etc) it does have an constructor, so its not creating an actual "main-object"
public class Main extends Application {
Sub sub = new Sub();
int a;
// stuff
public void aMethod() {
sub.subMethod();
}
}
Sub: this class solely surpose is to change the variable a, it does not contain a constructor to create a "sub-object"
public class Sub {
//stuff
subMethod(){
int a = 5;
}
if i put the line Main main; in the Sub class, the program will give me a nullpointer exception, if i'm calling the subMethod().
ok...i guess cause i didnt actually create the main object... so far so good.
BUT... if i put in the line Main main = new Main(); the program wont even start giving me an "exception while running application" error
the strange thing though is, if i put the line Main main = new Main(); in the subMethod...
subMethod(){
Main main = new Main();
int a = 5;
}
...the damn thing actually works...(well its slow, guess because with every calling of the method its creating a new object)
why is that so?
and how is it done correctly? :)
(using methods of other classes to "overwrite" variables)
regards
Red
You should not create more than one instance of Main in your program. Probably Main is not the best place to store mutable state (class members), but if you want that, you need to pass the instance of Main to subMethod (and make a public, or provide a public setter method):
public class Main extends Application {
Sub sub = new Sub();
public int a;
// stuff
public void aMethod() {
sub.subMethod(this);
}
}
public class Sub {
//stuff
subMethod(Main main){
main.a = 5;
}
So you want a method to change the value of another class's fields. There are a few ways to do this. If you have this class
public Class A {
private int a;
...
public void setA(int a) {
this.a = a;
}
}
You can do something like this
public Class B {
private static A instance;
....
public static void setA(int a) {
instance.setA(a);
}
}
Or you can take the A in as a parameter to the set method
public Class B {
...
public static void setA(A a, int val) {
a.setA(val);
}
}
If you want direct access to the fields on A you have to make them public (this is usually not what you want to do as it gives complete access rather than just giving just the access the other classes require)
Public Class A {
public int a;
...
}
Then you can do
Public Class B {
...
public static void setVal(A a, int val) {
a.a = val;
}
}
Also if you don't have the method setA in B as static you'll have to call it on an instance of B like
B b = new B();
b.setA(a, val);
Where as if it's static you call it on the class B
B.setA(a, val);