Say I want to solve a bunch of Project Euler problems in Java, and rather than give each problem class the boilerplate of its own main method, inherit it and have a "solve" method instead.
Is there a way of getting the problem class's name to print out along with the solution?
What I have:
abstract class Problem {
private static String problemName = ???
public static void main(String[] args) {
// If I could summon an instance of the sub-class then it would be easy
// Problem p = new ... what?
System.out.println(problemName + ": " + solve());
}
abstract static long solve();
// oops, you can't do abstract static in Java :(
}
then
public class Euler_001 extends Problem {
static long solve() {...}
}
The problem is that the various hacks to get the class name given in this answer return "Problem", not "Euler_001".
I guess I have to instantiate the problem class, but then how do I do that?
The static context does not help inheritance where the parent needs to call the child. Use instances with abstraction:
abstract class Problem {
public static void main(String[] args) throws Exception {
Problem problem;
//Now, depending on where the exact problem is specified:
//Class known at compile time
problem = new Euler_001();
//Class passed as parameter
problem = (Problem) Class.forName(args[0]).getConstructor().newInstance();
System.out.println(problem.getProblemName() + ": " + problem.solve());
}
abstract long solve();
abstract String getProblemName();
}
And the subclass will provide a normal implementation that overrides abstract methods:
class Euler_001 extends Problem {
#Override
long solve() {
return 0;
}
#Override
String getProblemName() {
return "????";
}
}
Depending on your configuration approach, you can create an instance of the concrete class based on the class name, inside the parent's main method.
This way, the Problem class can be called with:
java com.mypackage.Problem "com.mypackage.Euler_001"
Static variables and methods can not be overriden - they get replaced. So, as per my understanding we need to create instance of sub-class.
I checked -
Problem p = new Euler_001();
System.out.println(p.getClass().getSimpleName()); //prints Euler_001
Related
I'm trying to achieve the following:
I have a parent class, with some logic. In the child class, I "redefine" constants/properties. Is there any way to make the child properties accessible by methods defined in the parent class? Or to be more specific - is there any way to force the "out" method to write extended rather than base in the following example?
public class BaseTest {
public static final String x = "base";
public void out() {
System.out.println(x);
}
}
public class ExtendedTest extends BaseTest{
public static final String x = "extended";
}
public class Main {
public static void main(String[] args) {
BaseTest base = new BaseTest();
ExtendedTest extended = new ExtendedTest();
base.out(); // base (as expected)
extended.out(); // base (extended expected)
System.out.println(extended.x); // extended (as expected)
}
}
I come mainly from the world of PHP, where this approach works just fine. Dunno if I'm missing something or if the very design of Java does not allow this.
Thank you.
Note: This is not important whether the property is static or not. I just wanted to be able to override a property of any kind in a child class (just like I can override a method) which, on basis of the answers I've received so far, doesn't seem to be possible in Java. In PHP it is absolutely possible and that was why I asked the question.
static fields are not subject to inheritance. The x in the body of the out() method refers to BaseTest.x. Since you are not overriding out(), the body of the out() method still prints the value of BaseTest.x.
Static members are resolved at compile-time, and adding an ExtendedTest.x does not affect the also-existing BaseTest.x, which is what the BaseTest#out() method is linked to.
To accomplish what you're wanting, you need an overridden method:
public class BaseTest {
public String x() {
return "base";
}
public final void out() {
System.out.println(x());
}
}
public class ExtendedTest extends BaseTest {
#Override
public String x() {
return "extended";
}
}
This pattern is commonly used with an abstract method in the base class or interface to require the subclass to define an attribute such as a name or a key.
So I am a bit new to Java. I just got introduced to interfaces and i have to create a method that returns an instance of the interface Chassis
Below is the code:
public interface Chassis {
public String Chassis = "Chassis";
public static void main(String[] args) {
public String getChassisType() {
return Chassis;
}
The problem is, I keep getting error that abstract methods cannot have a body (as indicated by the blockquote) yet i had not declared my method as abstract.
What seems to be the problem?
You have two problems, You can't put a method inside another method, and you can't define a method like this in an interface in Java. In Java 8 you can do this
public interface Chassis {
String Chassis = "Chassis";
default String getChassisType(){
return Chassis;
}
}
I wouldn't define your public static void main inside an interface. While it is allowed now, most developers would find this confusing. See #Jürgen's answer, as this what most experienced developers would say I believe.
I would create another class like
public class Main {
public static void main(String... args) {
// an anonymous subclass so you have something to create/call.
System.out.println(new Chassis(){}.getChassisType());
}
}
An interface is a kind of abstract. It cannot be instantiated, It can have only declaration of methods and attributes not definition. You can only implement it in a class, if you do so in a class you must define all the methods which are declared in the interface. A main method need to be defined in order to execute the program. So it should not be placed inside an interface. change your code like this below
public interface chassis
{
String Chassis;
public String chassis();
}
public class example implements chassis
{
public String chassis()
{
Chassis="chassis";
return Chassis;
}
public static void main(String[] args)
{
System.out.println(new example().getChassisType());
}
}
This code would not work at all. A main method is only valid for classes, not for interfaces.
EDIT: as stated below the answer is not correct. But having a method inside a method still does not work. See the other answers.
//Vehicle.java
import java.util.Random;
class VehicleConstructor{
private int speed;
private int timeDriven;
private int run;
private int startSpeed; //Pradinis greitis
public VehicleConstructor() {
setSpeed();
System.out.println("Vehicle");
}
private void setSpeed(){
int minSpeed = 1;
int maxSpeed = 40;
Random random = new Random();
this.startSpeed = random.nextInt(maxSpeed - minSpeed + 1) + minSpeed;
}
protected int getSpeed(){
return startSpeed;
}
}
class Bicycle extends VehicleConstructor{
public void Bicycle(){
System.out.println(getSpeed());
}
}
public class Vehicle{
public static void main(String[] args){
Bicycle bicycle = new Bicycle();
}
}
I want to create object Bicycle which extends VehicleConstructor and call method getSpeed() from parent. The problem is that i get an error:
Error: Main method not found in class Bicycle, please define the main
method as: public static void main(String[] args)
As far as i know in Java constructors are with the same name as the class, so i have
public void Bicycle(){
System.out.println(getSpeed());
}
But error says that i need public static void main, and so the other classes also need to be with static, but i don't want this. Is it possible somehow create object without need of static method in it?
public void Bicycle(){ //This is a method
public Bicycle(){ //This is a constructor
Constructor's don't have any return type, not even void.
The error is self evident.. you dont have a main method, or for some reason, bicycle is defined as entry point when it should not be. After a second glance, looks like your Vehicle should be defined as the entry point, and its not.
p.s your class hierarchy is confusing.
create a separate class having main method to test (without this your program will not execute as it is the starting point) where you can create constructors of your classes
Your class works fine for me..What is the name of the file in which you have written code?File name should be equal to public class name..
I am guessing you are trying to run this class by itself. Java runtime needs that
public static void main(String[] args)
method when you try to run the class on its own. Try to create another Java class like Test.java that has main function and call the constructor inside it. Be sure to run Test.java otherwise you will keep getting the same error.
please , try to seperate the classes into seperates files, and name the files as the name of classes. then you add a public static void main(String[]arg) in the Bicycle class. then run it and you will see the results.
The problem is not at compile time, because even if you compile those files separately, they should compile fine. My guess is you are probably using an IDE (Netbeans or Eclipse) and you are not setting up Vehicle.java as the main class.
When a class extends another, it inherits all methods and variables of the superclass. Both methods and variables can be used differently in the subclass, if you define it differently in the subclass with the same signature.
Now Oracle distincts between overwriting and hiding (http://docs.oracle.com/javase/tutorial/java/IandI/override.html).
It says that an instance method overwrites its superclass's method, while a class method hides it.
"The distinction between hiding and overriding has important implications. The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass."
Lets assume I have 2 classes Yes and Maybe. Yes extends Maybe.
Maybe has String a.
class Maybe {
String a;
public static void printOut() {
System.out.println("Maybe");
}
public void printAndSet() {
a = "Maybe";
System.out.println(a);
}
}
class Yes extends Maybe {
public static void printOut() {
System.out.println("Yes");
}
pubilc void printAndSet() {
a = "Yes";
}
}
class Print{
public static void mail(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
Maybe.printOut();
Yes.printOut();
m.printAndSet();
y.printAndSet();
}
And I say: It will print out
maybe
yes
maybe
yes
But after I read the Oracle article I thought it would have to print out:
yes
yes
maybe
yes
Because the instance method overwrites its superclass method.
I'm quite sure I am right with the output, but I'm sure aswell, that Oracle knows
better so I'm thinking I just didn't understand the article.
It can't be true that when I call an instance method from an object of a superclass, that it uses the overwritten method.
So I do not understand why to distinguish overwriting and hiding!
Can someone help out?
Edit; Inserted code instead of describing the classes!
Static methods can't be overridden at all. They're not called polymorphically, since they don't act on an instance of the class, but on the class itself.
If you call Maybe.printOut(), it will call the static printOut() method defined in Maybe. The fact that there is also a method printOut() defined in Yes is irrelevant: those two methods have nothing in common, except their name.
Note that you could confirm or infirm your doubts by simply writing a program and executing it.
The problem with hiding methods only occurs when you start calling static methods on an instance of an object. This is very bad practice, and should never be done. If you don't respect this rule, and have the following:
Maybe m = new Maybe();
Maybe y = new Yes();
m.printOut(); // DON'T DO THAT: it should be Maybe.printOut();
y.printOut(); // DON'T DO THAT: it should be Maybe.printOut() or Yes.printOut();
the result will be maybe maybe, because in the case of static methods, what counts is not the concrete type of the objects (Maybe and Yes), but their declared type (Maybe and Maybe).
public class Parent {
public String test(){
return "p";
}
public static String testStatic(){
return "sp";
}
}
public class Child extends Parent {
public String test(){
return "c";
}
public static String testStatic(){
return "sc";
}
}
public class Demo{
public static void main(String[] args) {
Parent p =new Parent();
Child c = new Child();
Parent pc = new Child();
System.out.println(p.test());
System.out.println(c.test());
System.out.println(pc.test());
//Although this is not the correct way of calling static methods
System.out.println(p.testStatic());
System.out.println(c.testStatic());
System.out.println(pc.testStatic());
}
}
OUTPUT will be: - (static method vs instance method)
p
c
c
sp
sc
sp
Take the following example, based on your example:
public class SO11720216 {
static class Maybe {
public static void hidden() { System.out.println("static maybe"); }
public void overwritten() { System.out.println("instance maybe"); }
public void inherited() { hidden(); }
public void called() { overwritten(); inherited(); }
}
static class Yes extends Maybe {
public static void hidden() { System.out.println("static yes"); }
public void overwritten() { System.out.println("instance yes"); }
}
public static void main(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
m.called(); /* prints:
instance maybe
static maybe
*/
y.called(); /* prints:
instance yes
static maybe
*/
Yes.hidden(); /* prints: static yes */
y.hidden(); /* bad style! prints: static yes */
}
}
The call to overwritten will be overwritten by each derived class. So every method will use the implementation belonging to the current object. On the other hand, the call to hidden will always use the implementation of the defining class. Hence Maybe.called will always call Maybe.hidden, and never Yes.hidden. To call Yes.hidden, you'll have to do so from within a method in Yes, or using a qualified name.
To phrase this differently:
To overwrite a method means that whenever the method is called on an object of the derived class, the new implementation will be called.
To hide a method means that an unqualified call to that name (like the hidden() call in the inherited() method of my above example) in the scope of this class (i.e. in the body of any of its methods, or when qualified with the name of this class) will now call a completely different function, requiring a qualification to access the static method of the same name from the parent class.
Perhaps your confusion comes from the fact that you assumed overwriting to affect all calls to the method, even for objects of the base class.
I have a Super class and a bunch of subclasses. I want to have one field that has the same name in every single subclass, but I do not want it to be defined in the super class, or at least I do not want to use that value. This is what I have right now
public abstract class Big {
public String tellMe = "BIG";
public Big() {}
public void theMethod() {
System.out.println ("Big was here: " + tellMe() + ", " + tellMe);
}
public String tellMe() {
return tellMe;
}
}
public class Little extends Big{
public String tellMe = "little";
public Little(){}
public String tellMe() {
return "told you";
}
public static void main(String [] args) {
Little l = new Little();
l.theMethod();
}
}
When I run Little, this is the output
Big was here: told you, BIG
I am not sure why 'told you' is printed out while tellMe refers to "BIG". How can both be true?
My problem is that I want the method tellMe() to be in Big, and to have the variable tellMe (that it will actually return) to be defined in all the subclasses. The only way I can get this to work is as I have written, by rewriting the tellMe() method in each subclass. But doesn't that defeat the whole purpose of inheritance??? Please help
EDIT: I do not use the constructor in my subclasses. All I want is a field that can be set in all subclasses and a method in the super that uses those values. I don't understand why this isn't possible because every subclass would have to implement it, so it would make sense... If this simply is not possible, let me know please
Fields are not virtual, unlike methods. For this reason, it is a bad idea to declare fields with the same name as a field in another class in the hierarchy. The field referred to in theMethod is always going to be from Big (i.e. when you declare a field with the same name, it just hides the old field when in the scope of the replacing class, but doesn't replace it).
One solution would be to override a method that gets the field from the current class:
In theMethod replace the tellMe field with getTellMe() and for all classes override getTellMe() to return the correct value (or the field that hides the superclass's field).
You can overwrite the value of Big.tellMe in the constructor of Little.
get rid of:
public String tellMe = "little";
and change the Little constructor to:
public Little(){
tellMe = "little";
}
at that point, you can get rid of Little.tellMe() also.
What you are doing is hiding the super class field, not overriding it, as the Java documentation states.
And it's also stated that it's not a good idea to do it.
So, the dynamic lookup won't work as for a method. If the variable is read from the son class, it will take "its" field value.
On the top class, the other one.
What you can override in Java is the behaviour, so what I would suggest is to
define a method
public String tellMe() {
return "Whatever";
}
that you can override in the subclasses to return whatever string you need.
Instead of defining tellMe inside of Big (since you said you do not want to define/use that value in Big) you can create a function in Big:
public abstract String tellMeString();
And define that in each subclass like so (for Little):
public String tellMeString()
{
return "Little";
}
Then theMethod can execute:
System.out.println ("Big was here: " + tellMe() + ", " + tellMeString());
In this case you wouldn't have to define a variable "tellMe" at all, you just override tellMeString in each subclass to return different Strings.
Fields are not inherited as you are expected. You can access the super class' field (unless it is private) from subclass. But you cannot "override" field. This is why tellMe used by method implemented in super class Big uses variable defined in the same class.
If you want inheritance use methods. For example you can implement method "tellMe()" that returns "BIG" in super class and "little" in subclass:
class Big {
protected String tellMe() {
return "BIG";
}
}
class Little {
#Override
protected String tellMe() {
return "Little";
}
}
Alternatively you can initialize variable tellMe in constructor:
class Big {
private String tellMe;
public Big() {
this("BIG");
}
protected Big(String tellMe) {
this.tellMe = tellMe;
}
protected String tellMe() {
return "BIG";
}
}
class Little {
public Little() {
super("Little");
}
}
Now new Little().tellMe() will return "Little": the variable in super class was initialized when constructing the object; the method defined in super class returned this variable.
Methods can be overridden, fields are visible at the scope where they're called.
static class Big {
String field = "BIG";
String bark() { return "(big bark)"; }
void doIt() {
System.out.format("field(%s) bark(%s)\n", field,bark());
}
void doIt2() {
System.out.format("2:field(%s) bark(%s)\n", field,bark());
}
}
static class Small extends Big {
String field = "small";
String bark() { return "(small bark)"; }
void doIt2() {
System.out.format("2:field(%s) bark(%s)\n", field,bark());
}
}
public static void main(String... args) {
Big b = new Big();
b.doIt();
b.doIt2();
Small s = new Small();
s.doIt();
s.doIt2();
}
Output is:
field(BIG) bark((big bark))
2:field(BIG) bark((big bark))
field(BIG) bark((small bark))
2:field(small) bark((small bark))
since doIt() is defined in the Big class, it will always see the Big version of field. doIt2() is defined in Big, but overridden in Small. The Big.doIt2() sees the Big version of field, the Small.doIt2() version sees the Small version of field.
As others have pointed out, it's a pretty bad idea to do this - a better approach is to set the new value in the subclass constructor, or to use a method which is overridden.