Is it possible to get a Field through Java reflection if I have the field itself? It's a primitive float (public, no problem). I don't want to use its name as a String.
Example:
public class TVset {
public float voltageA;
public float voltageB;
public float voltageC;
public TVset(...) {...} // constructor
public void function() {...} // it changes voltages
}
class Voltmeter{
Object theObject;
Field theField;
Voltmeter(Object obj) {
theObject = obj;
Class theFieldClass = obj.getClass();
Class theContainerClass = theFieldClass.getDeclaringClass();
Field theField = ??? // <-- here I don't want to use a String
}
float getVoltage() {
return theField.getFloat(theObject);
}
}
TVset tv1 = new TVset(...);
TVset tv2 = new TVset(...);
Voltmeter meter = new Voltmeter(tv1.voltageB);
meter.getVoltage();
tv1.function();
meter.getVoltage(); <- should reflect the changed voltage
tv1.function();
meter.getVoltage(); <- should reflect the changed voltage
...
The effect is similar to passing the float by reference, but without wrapping it into a wrapper class.
I need to measure different voltages on different TV sets, just by changing the line:
Voltmeter meter = new Voltmeter(tv1.voltageB);
to something else, like:
Voltmeter meter = new Voltmeter(tv2.voltageA);
Is it possible to do it with reflection?
Thx
To use reflection you have to use a String. Instead of using a float you can use an object to wrap mutable float or a simple float[1];
BTW I wouldn't use float unless you have a really good reason, double suffers far less rounding error.
public class TVset {
public double[] voltageA = { 0.0 };
public double[] voltageB = { 0.0 };
public double[] voltageC = { 0.0 };
}
class Voltmeter{
final double[] theField;
Voltmeter(double[] theField) {
this.theField = theField;
}
double getVoltage() {
return theField[0];
}
}
// works just fine.
Voltmeter meter = new Voltmeter(tv1.voltageB);
EDIT: Using an abstract accessor. This is the fastest way to do this. AFAIK,the difference is less than 10 nano-seconds.
public abstract class Voltmeter{ // or use an interface
public abstract double get();
public abstract void set(double voltage);
}
public class TVset {
private double _voltageA = 0.0;
private double _voltageB = 0.0;
private double _voltageC = 0.0;
public final Voltmeter voltageA = new Voltmeter() {
public double get() { return _voltageA; }
public void set(double voltage) { _voltageA = voltage; }
}
public final Voltmeter voltageB = new Voltmeter() {
public double get() { return _voltageB; }
public void set(double voltage) { _voltageB = voltage; }
}
public final Voltmeter voltageC = new Voltmeter() {
public double get() { return _voltageC; }
public void set(double voltage) { _voltageC = voltage; }
}
}
Personally, if speed is critical, I would just use the fields directly by name. You won't get simpler or faster than that.
Just for completeness I've included the delegate way of solving this. I would also not recommend having your floats with public access.
public class stackoverflow_5383947 {
public static class Tvset {
public float voltageA;
public float voltageB;
public float voltageC;
public Tvset() {
}
public void function() {
voltageA++;
}
};
public static class Voltmeter {
private VoltageDelegate _delegate;
public Voltmeter(VoltageDelegate delegate) {
_delegate = delegate;
}
float getVoltage() {
return _delegate.getVoltage();
}
};
public static interface VoltageDelegate {
public float getVoltage();
}
public static void main(String[] args) {
final Tvset tv1 = new Tvset();
Voltmeter meter = new Voltmeter(new VoltageDelegate() {
public float getVoltage() {
return tv1.voltageA;
}
});
System.out.println(meter.getVoltage());
tv1.function();
System.out.println(meter.getVoltage());
tv1.function();
System.out.println(meter.getVoltage());
}
}
If you control the TVSet but need to use reflection for some reason, a good way to avoid errors is to write the method/field names that you need as String Constants in the TVSet class.
However if your concern is performance, reflection is not the way to go because accessing a field or method through reflection can be much slower than accessing through getters or directly.
Here a variant where you can give your float value instead of a string.
class Voltmeter{
Object container;
Field theField;
Voltmeter(Object obj, float currentValue) {
container = obj;
Class<?> containerClass = obj.getClass();
Field[] fields = containerClass.getFields();
for(Field f : fields) {
if (f.getType() == float.class &&
f.getFloat(container) == currentValue) {
this.theField = f;
break;
}
}
}
float getVoltage() {
return theField.getFloat(container);
}
}
Then call it like this:
Voltmeter meter = new Voltmeter(tv1, tv1.voltageB);
It works only if the voltages in the moment of Voltmeter creation are different (and not NaN), as it takes the first Field with the right value. And it is not really more efficient, I think.
I wouldn't really recommend this.
Related
In this Java class, note how use of the constructor has been disallowed and replaced with an interface driven builder that guides instantiation and does validation
public class Position implements Serializable {
private BigDecimal capital;
private BigDecimal tolerableRiskInPercentOfCapitalPerTrade;
private Direction direction;
private BigDecimal pricePerUnit;
private BigDecimal stopLossPricePerUnit;
private Position(){}
public final BigDecimal getTotalTolerableRiskPerTrade() {
return capital.multiply(tolerableRiskInPercentOfCapitalPerTrade.divide(new BigDecimal(100)));
}
public final BigDecimal getStopLossPerUnitLoss() {
if (direction.equals(Direction.LONG)){
return pricePerUnit.subtract(stopLossPricePerUnit);
} else {
return stopLossPricePerUnit.subtract(pricePerUnit);
}
}
public final BigDecimal getStopLossTotalLoss() {
return getStopLossPerUnitLoss().multiply(getUnitsToBuy());
}
public final BigDecimal getUnitsToBuy() {
BigDecimal result = getTotalTolerableRiskPerTrade().divide(getStopLossPerUnitLoss(), 0, BigDecimal.ROUND_DOWN);
if (capital.compareTo(result.multiply(pricePerUnit)) != 1){
return new BigDecimal(0);
} else {
return result;
}
}
public final BigDecimal getTotal() {
return getUnitsToBuy().multiply(pricePerUnit);
}
public static ICapital builder(){
return new Builder();
}
public interface ICapital {
ITolerableRiskInPercentOfCapitalPerTrade capital(final BigDecimal capital);
}
public interface ITolerableRiskInPercentOfCapitalPerTrade {
IDirection tolerableRiskInPercentOfCapitalPerTrade(final BigDecimal tolerableRiskInPercentOfCapitalPerTrade);
}
public interface IDirection {
IPricePerUnit direction(final Direction direction);
}
public interface IPricePerUnit {
IStopLossPricePerUnit pricePerUnit(final BigDecimal pricePerUnit);
}
public interface IStopLossPricePerUnit {
IBuild stopLossPricePerUnit(final BigDecimal stopLossPricePerUnit);
}
public interface IBuild {
Position build();
}
private static class Builder implements ICapital, ITolerableRiskInPercentOfCapitalPerTrade, IDirection, IPricePerUnit, IStopLossPricePerUnit, IBuild {
private final Position instance = new Position();
#Override
public Position build() {
return instance;
}
#Override
public ITolerableRiskInPercentOfCapitalPerTrade capital(final BigDecimal capital) {
basicValidate(capital);
instance.capital = capital;
return this;
}
#Override
public IDirection tolerableRiskInPercentOfCapitalPerTrade(final BigDecimal tolerableRiskInPercentOfCapitalPerTrade) {
basicValidate(tolerableRiskInPercentOfCapitalPerTrade);
if (tolerableRiskInPercentOfCapitalPerTrade.compareTo(new BigDecimal(100)) != -1) {
throw new IllegalArgumentException("riskInPercent must be lower than 100");
}
instance.tolerableRiskInPercentOfCapitalPerTrade = tolerableRiskInPercentOfCapitalPerTrade;
return this;
}
#Override
public IPricePerUnit direction(final Direction direction) {
if (direction==null) {
throw new IllegalArgumentException("argument can't be null");
}
instance.direction = direction;
return this;
}
#Override
public IStopLossPricePerUnit pricePerUnit(final BigDecimal pricePerUnit) {
basicValidate(pricePerUnit);
instance.pricePerUnit = pricePerUnit;
return this;
}
#Override
public IBuild stopLossPricePerUnit(final BigDecimal stopLossPricePerUnit) {
basicValidate(stopLossPricePerUnit);
if (instance.direction.equals(Direction.LONG) && instance.pricePerUnit.compareTo(stopLossPricePerUnit) != 1) {
throw new IllegalArgumentException("price must be higher than stopLossPrice");
}
if (instance.direction.equals(Direction.SHORT) && stopLossPricePerUnit.compareTo(instance.pricePerUnit) != 1) {
throw new IllegalArgumentException("stopLossPrice must be higher than price");
}
instance.stopLossPricePerUnit = stopLossPricePerUnit;
return this;
}
}
protected static void basicValidate(final BigDecimal bigDecimal) {
if (bigDecimal == null) {
throw new IllegalArgumentException("argument can't be null");
}
if (!(bigDecimal.signum() > 0)) {
throw new IllegalArgumentException("argument must have positive signum");
}
}
}
resulting in instantiation like this
Position.builder()
.capital(new BigDecimal(10000))
.tolerableRiskInPercentOfCapitalPerTrade(new BigDecimal(2))
.direction(Direction.LONG)
.pricePerUnit(new BigDecimal(25))
.stopLossPricePerUnit(new BigDecimal(24))
.build();
Trying to port code between languages isn't easy and identical functionality can't and shouldn't be expected. That said, are there any ways of emulating similar functionality in JavaScript? (vanilla or through some modules/libraries if necessary)
There are a few ways to do this.
One option is to do it almost exactly the same way: With a builder object that has methods to specify details and a build method (or similar) that you call to get the final object. The resulting call to build the object would look almost exactly the same (modulo type names and such).
Another option is to take advantage of JavaScript's object initializer syntax (aka "object literals") to have an "options" object that you pass into a constructor for the Position, like this:
function Position(options) {
if (/*...the options aren't valid...*/) {
throw new Error(/*...*/);
}
this.capital = options.capital;
// ...
}
Usage:
var p = new Position({
capital: 10000,
tolerableRiskInPercentOfCapitalPerTrade: 2,
direction: Direction.LONG,
pricePerUnit: 25,
stopLossPricePerUnit: 24
});
Inside the constructor, if you're going to use the data from options directly as properties on the new instance, you can use a function top copy them over:
function applyOptions(instance, options) {
Object.keys(options).forEach(function(key) {
instance[key] = options[key];
});
return instance;
}
Then:
function Position(options) {
if (/*...the options aren't valid...*/) {
throw new Error(/*...*/);
}
applyOptions(this, options);
}
(jQuery, if you use it, has an $.extend function that basically does this; Underscore, if you use it, has _.extend and _.extendOwn.)
But if you're going to be doing some manipulation of the options before storing them as properties on the new instance, a blind copy like that wouldn't be ideal.
I'm developing a graphical user interface in Java and relying on the standard MVC design pattern in which I have a View which should provide an up-to-date representation of the state of the Model.
I have an ObserverTextField class within the View which subclasses JTextField and registers itself as an observer of part of the Model. When this part of the Model changes, it calls this observer's notify method, passing the integer value. The class then sets its displayed text to the user.
However, I would like to be able to control the representation of the number at run-time. I could pass a NumberFormat to the class, but that doesn't seem able to represent the value as, say, 1/1000th of its actual value.
E.g. if the model stores the value of a current in milliamps, and I want it shown to the user in terms of amps, is there some kind of object I could construct and pass to the ObserverTextField to let it do that?
Below is an example of the code using an instance of NumberFormat, which I would like to replace with something more powerful:
public class ObserverTextField extends JTextField implements Observer {
private static final long serialVersionUID = 1L;
private NumberFormat formatter;
#Override
public void notify(Object value) {
if(formatter == null) {
setText(String.valueOf(value));
} else {
setText(formatter.format((int)value));
}
}
public NumberFormat getFormat() {
return formatter;
}
public void setFormat(NumberFormat formatter) {
this.formatter = formatter;
}
}
If there isn't such a thing, I could create my own, but I'd prefer to make sure something like that doesn't already exist in Java's standard library first.
Your Observer can have a utility function that will Format your value as so:
private static DecimalFormat df = new DecimalFormat("#.000");
public static String getFormattedValue(double value, double factor) {
return df.format(value * factor);
}
Here is an example in main
public static void main(String[] args) throws Exception {
double value = 3560;
System.out.println(value + " milliamps");
//Milliamps to centiamps is a factor of .1
System.out.println(getFormattedValue(value, .1) + " centiamps");
//Milliamps to deciamps is a facotr of .01
System.out.println(getFormattedValue(value, .01) + " deciamps");
//Milliamps to amps is a factor of .001
System.out.println(getFormattedValue(value, .001) + " amps");
}
The output:
3560.0 milliamps
356.000 centiamps
35.600 deciamps
3.560 amps
Java 8 promises a nice solution:
textField.setFormat((n) -> (n.intValue() / 1000) + " mA");
private Function<Number, String> formatter = (n) -> n + " A";
#Override
public void notify(Object value) {
setText(formatter.apply((Number)value));
}
public void setFormat(Function<Number, String> formatter) {
this.formatter = formatter;
}
Judging from the answers, there doesn't seem to be an in-built method in Java for performing arbitrary conversions on numbers, so I put together a simple but usable custom implementation. I created a utility class MathSequence:
import java.util.LinkedList;
import java.util.List;
public class MathSequence {
private interface MathOperation {
double operate(double value);
}
private class AddOperation implements MathOperation {
private double operand;
public AddOperation(double operand) {
this.operand = operand;
}
public double operate(double value) {
return value + operand;
}
}
private class SubtractOperation implements MathOperation {
private double operand;
public SubtractOperation(double operand) {
this.operand = operand;
}
public double operate(double value) {
return value - operand;
}
}
private class MultiplyOperation implements MathOperation {
private double operand;
public MultiplyOperation(double operand) {
this.operand = operand;
}
public double operate(double value) {
return value * operand;
}
}
private class DivideOperation implements MathOperation {
private double operand;
public DivideOperation(double operand) {
this.operand = operand;
}
public double operate(double value) {
return value / operand;
}
}
private List<MathOperation> operations;
public MathSequence() {
operations = new LinkedList<MathOperation>();
}
public void appendAddOperation(double operand) {
operations.add(new AddOperation(operand));
}
public void appendSubtractOperation(double operand) {
operations.add(new SubtractOperation(operand));
}
public void appendMultiplyOperation(double operand) {
operations.add(new MultiplyOperation(operand));
}
public void appendDivideOperation(double operand) {
operations.add(new DivideOperation(operand));
}
public void clearOperations() {
operations.clear();
}
public double process(double value) {
for(MathOperation operation : operations) {
value = operation.operate(value);
}
return value;
}
}
Then I changed my ObserverTextField class:
public class ObserverTextField extends JTextField implements Observer {
private static final long serialVersionUID = 1L;
private NumberFormat formatter;
private MathSequence sequence;
public ObserverTextField() {
formatter = new DecimalFormat("");
sequence = new MathSequence();
}
#Override
public void notify(Object value) {
int integerValue = (int)value;
setText(formatter.format(sequence.process(integerValue)));
}
public NumberFormat getFormat() {
return formatter;
}
public void setFormat(NumberFormat formatter) {
this.formatter = formatter;
}
public MathSequence getSequence() {
return sequence;
}
public void setSequence(MathSequence sequence) {
this.sequence = sequence;
}
}
I can then write code like the following:
MathSequence sequence = new MathSequence();
sequence.appendDivideOperation(1000);
NumberFormat formatter = new DecimalFormat("0.000");
ObserverTextField actuatorCurrentTextField;
actuatorCurrentTextField = new ObserverTextField();
actuatorCurrentTextField.setSequence(sequence);
actuatorCurrentTextField.setFormat(formatter);
This will display the representation as I like it. Because of this approach, I don't hardcode the representation of values within the ObserverTextField classes themselves, and so I'm free to vary the representation at run-time and re-use code pretty easily. This is why I couldn't accept suggestions along the lines of "why not just do (int)value/1000?".
I'll accept one of the other answers even though I'll likely stick with this one for the time being, since they're pretty informative.
I'm working on program/game where I have static utility class with params.
class ParamsGeneral {
public static final int H_FACTOR = 100;
public static int MAX_SCORE = 1000;
...
}
then I need to override this values in some specific cases, for example playing on map with limited score. So I did following:
class ParamsLimited extends ParamsGeneral {
public static int MAX_SCORE = 500;
// other params stay same
}
And the intended usage is following:
class Player {
ParamsGeneral par;
public Player() {
if(onLimitedMap()){
par = new ParamLimited();
}
}
public boolean isWinner() {
if(this.score == par.MAX_SCORE) {
return true;
}
return false;
}
}
I haven't actually tested this code, because IDE is complaining about calling static field through instance and also about field hiding. I clearly see that this code is stinks, so is there a way to achieve this or do I have to write each param class separately?
PS: I know I shoud make the default class abstract and use getters, I'm just curious if there is a way to make the values accesible statically.
You cannot override static members - in Java, neither methods nor fields could be overriden. However, in this case it does not look like you need to do any of that: since you have an instance of ParamsGeneral in the par variable, a non-static method would do what you need with the regular override.
class ParamsGeneral {
public int getMaxScore() {
return 1000;
}
}
class ParamsLimited extends ParamsGeneral {
#Override public int getMaxScore() {
return 500;
}
}
...
public boolean isWinner() {
// You do not need an "if" statement, because
// the == operator already gives you a boolean:
return this.score == par.getMaxScore();
}
I wouldn't use subclassing for a general game vs a limited game. I would use an enumeration, like:
public enum Scores {
GENERAL (1000),
LIMITED (500),
UNLIMITED (Integer.MAX_INT);
private int score;
private Scores(int score) { this.score = score; }
public int getScore() { return score; }
}
Then, when constructing a game, you can do:
Params generalParams = new Params(Scores.GENERAL);
Params limitedParams = new Params(Scores.LIMITED);
And so forth.
Doing it this way allows you to change the nature of your game while keeping your values centralized. Imagine if for every type of parameter you think of you have to create a new class. It could get very complicated, you could have hundreds of classes!
Simplest solution is to do this:
class ParamsGeneral {
public static final int H_FACTOR = 100;
public static final int MAX_SCORE = 1000;
public static final int MAX_SCORE_LIMITED = 500;
...
}
class Player {
int maxScore;
public Player() {
if(onLimitedMap()){
maxScore = ParamsGeneral.MAX_SCORE_LIMITED;
}
else {
maxScore = ParamsGeneral.MAX_SCORE;
}
}
public boolean isWinner() {
if(this.score == this.maxScore) {
return true;
}
return false;
}
}
No need to have an instance of ParamsGeneral, it is just a collection of static definitions for your game.
Have MAX_SCORE be private static with public static getters; then you can call ParamsGeneral.getMaxScore and ParamsLimited.getMaxScore and you'll get 1000 and 500 respectively
I am a beginner in Java and i trying to understand the abstract classes.
Below is the code that I've written; the question is: how do i write a method that will return an instance of that class.
public abstract class VehicleEngine
{
protected String name;
protected double fabricationCons;
protected double consum;
protected int mileage;
public VehicleEngine(String n, double fC)
{
name = n;
fabricationCons = fC;
mileage = 0;
consum = 0;
}
private void setFabricationCons(double fC)
{
fabricationCons = fC;
}
public abstract double currentConsum();
public String toString()
{
return name + " : " + fabricationCons + " : " + currentConsum();
}
public void addMileage(int km)
{
mileage += km;
}
public double getFabricationConsum()
{
return fabricationCons;
}
public String getName()
{
return name;
}
public int getMileage()
{
return mileage;
}
//public VehicleEngine get(String name){
//if(getName().equals(name)){
//return VehicleEngine;
//}
//return null;
//}
}
public class BenzinVehicle extends VehicleEngine
{
public BenzinVehicle(String n, double fC)
{
super(n, fC);
}
#Override
public double currentConsum()
{
if (getMileage() >= 75000) {
consum = getFabricationConsum() + 0.4;
} else {
consum = getFabricationConsum();
}
return consum;
}
}
public class DieselVehicle extends VehicleEngine
{
public DieselVehicle(String n, double fC)
{
super(n, fC);
}
#Override
public double currentConsum()
{
int cons = 0;
if (getMileage() < 5000) {
consum = getFabricationConsum();
} else {
consum = getFabricationConsum() + (getFabricationConsum() * (0.01 * (getMileage() / 5000)));
}
return consum;
}
}
This is the main.
public class Subject2
{
public static void main(String[] args)
{
VehicleEngine c1 = new BenzinVehicle("Ford Focus 1.9", 5.0);
DieselVehicle c2 = new DieselVehicle("Toyota Yaris 1.4D", 4.0);
BenzinVehicle c3 = new BenzinVehicle("Citroen C3 1.6",5.2);
c1.addMileage(30000);
c1.addMileage(55700);
c2.addMileage(49500);
c3.addMileage(35400);
System.out.println(c1);
System.out.println(c2);
System.out.println(VehicleEngine.get("Citroen C3 1.6")); //this is the line with problems
System.out.println(VehicleEngine.get("Ford Focus "));
}
}
And the output should be:
Ford Focus 1.9 : 5.0 : 5.4
Toyota Yaris 1.4D : 4.0 : 4.36
Citroen C3 1.6 : 5.2 : 5.2
null
You can not return an instance of an abstract class, by definition. What you can do, is return an instance of one of the concrete (non-abstract) subclasses that extend it. For example, inside the VehicleEngine you can create a factory that returns instances given the type of the instance and the expected parameters, but those instances will necessarily have to be concrete subclasses of VehicleEngine
Have a look at the Factory Method pattern. Your concrete classes will implement an abstract method that returns a class instance.
Abstract classes do not keep a list of their instances. Actually no Java class does that. If you really want to do that, you could add a static map to VehicleEngine like this:
private static Map<String, VehicleEngine> instanceMap = new HashMap<String, VehicleEngine>();
and change your get method to a static one like this:
public static VehicleEngine get(String name) {
return instanceMap.get(name);
}
and add this line to the end of the constructor of VehicleEngine:
VehicleEngine.instanceMap.put(n, this);
this way every new instance created puts itself into the static map. However this actually is not a good way to implement such a functionality. You could try to use a factory to create instances, or you could consider converting this class into an enum if you will have a limited predefined number of instances.
I am trying to understand extending inner classes in Java. I have read around but nothing I found quite answers my question. So here goes...
I have...
public class Pie{
protected Slice[] slices;
// Pie constructor
public Pie(int n){
sliceGenerator(n)
}
private void sliceGenerator(int n){
slices = new Slice[n];
final float sweepAngle = 360.0f/(float)n;
float startAngle = 0;
for (int i=0;i<n;i++){
slices[i] = new Slice(startAngle);
startAngle += sweepAngle;
}
}
#Override
public String toString(){
for (Slice s:slices){
s.toString();
}
}
// Inner class...
public class Slice{
public Slice(float startAngle){
//set some private fields based on startAngle and generic pie
}
#Override
public String toString(){
return **string based on private fields**
}
}
}
Then I extend this...
public class ApplePie extends Pie{
protected Slice[] slices;
// Apple Pie constructor
public ApplePie(int n){
super(n);
}
// Inner class...
public class Slice extends Pie.Slice{
public Slice(float startAngle){
super(startAngle);
//set some **additional** private fields based on startAngle **specific to apple pie** appleness or something
}
#Override
public String toString(){
return **string based on apple pie specific private fields**
}
}
}
Now, when I make an Apple pie and call its toString method, like so...
ApplePie ap = new ApplePie(8);
System.out.println(ap.toString());
I do not get information about the apple pie slices, but information about the pie slices. It ignores my toString override, or more likely ignores my apple pie Slice. How can I arrange it such that apple pie slices refer to ApplePie?
Any help much appreciated! Sorry for pie references - it is the actual class I am working with...
I've changed your code to meet your requirements.
Your super class Pie is about to create a new instance of Slice, but the child class ApplePie's Slice does not override the Slice method of its super class'.
I added the functions below to enable the child class to create its own Slice.
protected void newSliceArray(int n) {
slices = new Slice[n];
}
protected Slice newSlice(float startAngle) {
return new Slice(startAngle);
}
Pie.java:
public class Pie {
private int a = 1;
protected Slice[] slices;
// Pie constructor
public Pie(int n) {
sliceGenerator(n);
}
private void sliceGenerator(int n) {
newSliceArray(n);
final float sweepAngle = 360.0f / n;
float startAngle = 0;
for (int i = 0; i < n; i++) {
slices[i] = newSlice(startAngle);
startAngle += sweepAngle;
}
}
protected void newSliceArray(int n) {
slices = new Slice[n];
}
protected Slice newSlice(float startAngle) {
return new Slice(startAngle);
}
#Override
public String toString() {
String t = "";
for (Slice s : slices) {
t += s.toString();
}
return t;
}
// Inner class...
public class Slice {
public Slice(float startAngle) {
// set some private fields based on startAngle and generic pie
}
#Override
public String toString() {
return "" + a;
}
}
}
ApplePie.java:
public class ApplePie extends Pie {
private int b = 2;
// protected Slice[] slices;
// Apple Pie constructor
public ApplePie(int n) {
super(n);
}
protected void newSliceArray(int n) {
slices = new Slice[n];
}
protected Slice newSlice(float startAngle) {
return new Slice(startAngle);
}
// Inner class...
public class Slice extends Pie.Slice {
public Slice(float startAngle) {
super(startAngle);
// set some **additional** private fields based on startAngle **specific to apple pie**
// appleness or something
}
#Override
public String toString() {
return b + "";
}
}
}
Test:
public static void main(String[] args) {
ApplePie ap = new ApplePie(8);
System.out.println(ap.toString());
}
The code will print 22222222
In your superclass, you are creating and storing Pie.Slice objects:
private void sliceGenerator(int n){
slices = new Slice[n];
final float sweepAngle = 360.0f/(float)n;
float startAngle = 0;
for (int i=0;i<n;i++){
slices[i] = new Slice(startAngle);
startAngle += sweepAngle;
}
}
These are the same objects being used by Pie.toString (which ApplePie doesn't override by the way).
Extending Pie with ApplePie and extending Pie.Slice with ApplePie.Slice doesn't change this. The new Slice(startAngle) in the above code does not magically switch to instantiating something different.
Aside from that, your Pie.toString() isn't returning anything - it shouldn't even compile:
#Override
public String toString(){
for (Slice s:slices){
s.toString();
}
}
I'm guessing you want to return a String representing all the slices. This would be a quick solution for example:
#Override
public String toString() {
return Arrays.toString(slices);
}
(Arrays.toString is just a utility method to get a String representing of an array.)
The answer lies within your program. When you instantiate Slice class, it gives call to the super class and invokes sliceGenerator. This method internally creates instances of Pie.Slice and not ApplePie.Slice. To get around this, make sliceGenerator method protected and override it in Apple.Slice class. Create the instances of Apple.Slice and it should work.