Reputation: 45
I'm trying to build a library of classes that I can use in future Swift game projects (with minimal code adjustments) that will be used to create subclasses more specific to the current project I'm working on. However, I've run into a problem with initializing other classes with "this" in the super() method call in the constructor. This is the problem in code form:
public class App extends JFrame {
public App(AppRunner appRunner, AppPanel appPanel) {
this.appRunner = appRunner;
this.appPanel = appPanel;
}
}
public class Pong extends App {
public App() {
super(new AppRunner(10, this), new AppPanel(this));
}
}
This sends an error relating to using the "this" variable before the class has been initialized.
I considered using abstract methods in the App class and having sub classes implement them but decided I didn't like that. The plan (in code form):
public abstract class App extends JFrame {
public App() {
this.appRunner = initializeAppRunner();
this.appPanel = initializeAppPanel();
}
abstract AppRunner initializeAppRunner();
abstract AppPanel initializeAppPanel();
}
I also tested an approach using a little bit of generics and reflection (which I know very little about). I also don't love this because I can't change the classes' constructor parameters very easily. The following is my current code:
public class App extends JFrame {
public App(Class<? extends AppRunner> appRunnerClass, Class<? extends AppPanel> appPanelClass) {
try {
this.appRunner = appRunnerClass.getConstructor(Integer.class, App.class).newInstance(10, this);
this.appPanel = appPanelClass.getConstructor(App.class).newInstance(this);
} catch (Exception e) {
e.printStackTrace();
}
add(appPanel);
}
}
public class Pong extends App {
public Pong() {
super(AppRunner.class, PongPanel.class);
}
}
I guess I'm wondering if their a simpler way to do this or if I should use the generics/abstract methods example.
Upvotes: 3
Views: 126
Reputation: 8705
Any problems with just using:
public Pong() {
appRunner = new AppRunner(10, this);
appPanel = new AppPanel(this);
}
—-
You can pass a lambda function to the App constructor, allowing you to customize the creation of the utility classes, but having the App super class create these classes.
See the Function interface.
class App extends ... {
App( Function<App, AppRunner> runner_creator,
Function<App, AppPanel> panel_creator) {
appRunner = runner_creator.apply(this);
appPanel = panel_creator.apply(this);
}
class Pong extends App {
Pong() {
super(
app -> new PongRunner(10, app),
app -> new PongPanel(app));
}
}
You are passing lambda function (without any this
references) to the super class, so the derived class controls how the utility classes are created, and what specific class is used.
Note: These utility classes are constructed using the super classes’s this
reference, which is an App
, not the derived classes type.
Upvotes: 1