So, I created a simple class named Test, as follows:
import prog.utili.IntegerB;
//It's a custom class
class Test
{
public static void main(String[] args)
{
IntegerB a = new IntegerB(1);
IntegerB b = new IntegerB(2);
IntegerB sum = a.plus(b);
System.out.println(sum);
}
}
I wanted to practise with inheritance so I created two custom classes. Fraction...
package prog.utili;
public class Fraction
{
private int num;
private int den;
public Fraction(int x, int y)
{
[...]
}
public Fraction(int x)
{
this(x, 1);
}
public Fraction plus(Fraction f)
{
int n = this.num * f.den + this.den * f.num;
int d = this.den * f.den;
return new Fraction(n, d);
}
[...]
}
...and IntegerB:
package prog.utili;
public class IntegerB extends Fraction
{
public IntegerB(int num)
{
super(num);
}
public IntegerB plus(IntegerB other)
{
return (IntegerB)this.plus(other);
}
}
The problem is I keep getting the same error:
at prog.utili.IntegerB.plus(IntegerB.java:11)
I know I could simply solve the problem by just deleting the last method on IntegerB and replacing the 9th line of Test.java with
IntegerB sum = (IntegerB)a.plus(b)
but I absolutely want to do it using the inheritance rules over the "plus" method!
To implement the method plus(IntegerB), you call plus(IntegerB), which calls plus(IntegerB), etc. etc. until you get a StackOverflowError.
Provide an actual implementation for your method:
return new IntegerB(this.getNum() + other.getNum());
or
return new IntegerB(super.plus(other).getNum());
Also note that replacing the last line of Test.java by
IntegerB sum = (IntegerB)a.plus(b);
wouldn't work, since the plus() method in Fraction doesn't return an IntegerB, but a Fraction. You would thus get a ClassCastException.
The problem here is that IntegerB.plus does not override Fraction.plus, it overloads it. This is because the argument types are different. Thus when IntegerB.plus calls this.plus(other), it ends up calling itself, which then calls itself, which then calls itself until you get a StackOverflow (thus sending you to stackoverflow : )).
It seems like you want to call plus(Fraction) instead of plus(IntegerB). To do that, you can explicitly upcast other:
return plus((Fraction) other);
This cast has no effect other than to tell the compiler that you want to call the version of plus that handles Fractions, even though you know you have an IntegerB.
However, this method would not return an IntegerB, but just a Fraction whose denominator is 1. You could conceivably override plus to return an IntegerB if the denominator of the result is 1, but that might lead to unexpected situations where a.plus(b) is not equal to b.plus(a) because one is a Fraction while the other is an IntegerB. Alternatively, you could return IntegerB objects from Fraction.plus when possible.
Related
I have to follow the below UML diagram to design a programme.
The programme is supposed to generate 2 random integers, and ask user for input the answer to the sum of said integers.
However, I am not sure how to make use of the method static void getTwoIntegers(MyInteger m, MyInteger n) , or what to put inside it.
I have tried initialising 2 MyInteger objects with MyInteger int_1 = new MyInteger(m); and (n) in this method, but get a "cannot be resolved" error everytime I call its getter method int_1.getInteger();
And since the method getTwoIntegers is void, I cannot just return 2 random integers. I'm truly stuck on how to utilise this method
Any ideas? Thanks so much
Simple demo of what your implementation can accomplish.
The MyInteger objects passed as parameters (m and n) can be modified by the implementation of getTwoIntegers using the setInteger method of the class.
public class Main
{
public static void main(String[] args) {
MyInteger a = new MyInteger(333);
MyInteger b = new MyInteger(444);
System.out.println("before: " + a.getInteger() + "," + b.getInteger());
getTwoIntegers(a,b);
System.out.println("after: " + a.getInteger() + "," + b.getInteger());
}
public static class MyInteger {
private int val;
public MyInteger() { val = 0; }
public MyInteger(int v) { val = v; }
public void setInteger(int n) { this.val = n; }
public int getInteger() { return val; }
}
static void getTwoIntegers(MyInteger m, MyInteger n) {
// in your case modify implementation to produce random numbers
m.setInteger(222);
n.setInteger(555);
}
}
Prints:
before: 333,444
after: 222,555
Gardener's answer nailed it. For the records, I'd like to share some more thoughts.
This class diagram is misleading. The parameters of an UML operation have a direction that should be indicated in front of the parameter name. It can be in, out, inout. If the direction is omitted in the diagram, UML assumes that it's an in argument. Which assumes that the parameter is not muted by the operation.
If it would have been correctly specified as getTwoIntegers(out m: MyInteger, out n: MyInteger) (yes, UML syntax order is slightly different from Java), you would have understood that the values of m and n are provided for the output of the values of the operation, and not as input. And indeed, as Gardener explained, in Java you can provide a class object that can then be mutated to store the results; because class objects are passed by reference (i.e. it's the same object that is used and not a copy). This is by the way why a class MyInteger is used in this lab instead of a built-in type int.
Other unrelated UML remarks: there is no static type modifier keyword in UML. Either is it marked as {static} or is it underlined. Last but not least, there should be no multiplicity on a dashed dependency arrow. Multiplicities are for associations, i.e. structural relationships.
I recently started to learn about generics in Java, and I understand the basic concepts of generics. However, one thing I don't understand is that I don't know why the following method doesn't work:
public class Generics<T extends Number> {
T num;
Generics(T n){
num = n;
}
//...
T timesTwo() { //Return the value that's twice as much as 'num'
return num * 2;
}
}
It was my first approach, and I kind of understand why it is not working. The error message said: The operator * is undefined for the argument types(s) T, int.
I guess Java couldn't multiply the T and int type together. (But shouldn't the compiler be able to auto-unbox T since it's involved in an expression AND the class extends Number?)
So I gave up on this method and tried to replace it with this method:
T times(T i) { //This method was supposed to receive another T object as
//an argument and multiply them together, then return the output
return num * i;
}
But once again, the exact same error message appeared (the only change was that int was replaced by T).
Why is the code not working, and how can I fix it?
I agree with the first two comments. Also, it's not a generics problem, it's just that the method doesn't work because it's not supposed to work because the boxing assumption you concluded doesn't apply here.
Autoboxing and Unboxing are supplied for some of the Number types but not all. See table below: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
So while this works the way you expect (because both types are in the supported table):
public static void main(String[] args) {
Integer a = 3;
Integer b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
This intuitively equivalent code will NOT work:
public static void main(String[] args) {
Number a = 3;
Number b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
In fact, from the Compiler's perspective, it gives you the same cross-eyed look you would get if you tried this:
public static void main(String[] args) {
String a = "what does it even mean to multiply a string with a number..??";
Byte b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
So to finish the point, from the compiler's perspective, since auto-boxing does not apply, it's just as confused as to how to multiply two Numbers as it is how to multiply two other random objects like a String and a Byte and reports the error accordingly
So, I have to create 68 different summing methods using the datatypes, int, float, double and short. The class is called, OverloadingSums. Here is an example of one the methods.
public double sum(double x, float y, int z)
{
return x+y+z;
}
Now I'm being asked to create a class called ZeroSum, essentially copying OverloadingSum and returning everything to zero. Here is an example.
public double sum(double x, float y, int z)
{
return 0;
}
Then I'm being asked to create another class called RealSum, which will extend the ZeroSum class. I'm a little confused about the wording of this assignment, not sure if the stackoverflow community could help but I'm just extremly confused.
Here is the assignment requirements:
Now that we have thoroughly explored overloading we are going to
explore overriding. Create a class called ZeroSum.java. Take all of
the methods from OverloadingSum.java and change them to return all
zeros in ZeroSum.java. Next, create a class called RealSum.java. This
class, RealSum, will extend the ZeroSum class. Having all zeros for
our sums isn't very useful. We will need to override the parent, or
super class methods to produce real results. Create the necessary
methods to override all of those in the ZeroSum.java. When you are
done run your classes against DrivingSum.java.
This is what I have in my main method:
public class DrivingSum {
public static void main(String[] args) {
int x = 10;
int y = 20;
// x + y = 30....yay?
ZeroSum zero= new ZeroSum();
RealSum real= new RealSum();
System.out.println("Calling ZeroSum " + zero.sum(x,y) );
System.out.println("Calling ZeroSum " + real.sum(x,y) );
}
}
So, from how I'm understanding this I wrote the following code:
public class ZeroSum extends RealSum{
public double sum(double x, float y, int z)
{
return super.sum(x,y,z);
}
This will grab the method from RealSum, instead of using the sum method located in the ZeroSum class. So when I run the main method, zero.sum(x,y) gives me 30.
The confusion comes from the fact that the assignment asks me to set everything in ZeroSum returning to zero. If I extend ZeroSum to RealSum, it doesn't really make a difference. Am I doing this correctly? or Am I just overthinking this way too much?
The goal of this assignment is to explore overriding concept, where function executed depends on type of object it called upon on run time, so you will have something like this :
public class ZeroSum {
public double sum(double x, float y)
{
return 0;
}
}
public class RealSum extends ZeroSum{
public double sum(double x, float y)
{
return x+y;
}
}
public class DrivingSum {
public static void main(String[] args) {
int x = 10;
int y = 20;
// x + y = 30....yay?
ZeroSum zero= new ZeroSum();
ZeroSum real= new RealSum();
System.out.println("Calling ZeroSum " + zero.sum(x,y) ); //here the sum will return zero
System.out.println("Calling ZeroSum " + real.sum(x,y) ); //here the sum will return 30
}
I believe he's trying to make a point in which whatever you write in the parent class is transferred (this is called inheritage) to the child. You can override this by writing a method in the child class using the same name and arguments as the parent class' method.
I also believe you read the assignment a bit wrong, it said:
This class, RealSum, will extend the ZeroSum class.
I interpret this as RealSum is the child to ZeroSum, not the other way around as such:
public class RealSum extends ZeroSum{
//code code code
}
This means everything in ZeroSum is set to 0 and RealSum set new values, not using the super. I'm not betting my hand this is correct but try to read the assignment again after a break and some fresh air :)
Hope this helps!
Is it necessary to always initialise the result variable in the function
For example
Public class Calculator
result=addition(a,b);
Public static int addition(int a, int b)
int result;
result =a+b;
return result;
You don't need to have a result variable at all. You need to make sure that every possible way that execution can reach the end of your function (without just throwing an exception) means you get to a return statement, and every return statement has an appropriate express to evaluate, but that doesn't mean you need a separate variable. Your example could be written as:
public static int addition(int a, int b) {
return a + b;
}
If you do use a variable, you'll need to make sure it's definitely assigned before you can read from it, including in a return statement. For example, this won't work because result hasn't been definitely assigned:
public static int addition(int a, int b) {
int result;
if (a < b) {
result = a + b;
}
return result; // Invalid! result may not have a value
}
Where possible, it's generally a good idea to initialize a variable at the point of declaration. So if I were writing this code and wanted a result variable, I'd have:
public static int addition(int a, int b) {
int result = a + b;
return result;
}
Now, looking at your sample code again, you've got another variable used when you call the method:
result=addition(a,b);
It's not clear where that variable would be declared (which is one reason to avoid just posting pseudo-code in questions) but it's completely separate from the result variable in addition, which is local to the addition method. The two variables happen to have the same name, but they're otherwise unrelated. For example, you could easily have:
int sum = addition(a, b);
or call another method with the result instead of assigning it to a variable:
System.out.println(addition(a, b));
Or you could just ignore it entirely:
addtion(a, b); // Valid, but pointless unless there are side-effects
I am watching a lecture from the University of California at Berkeley about creating arrays in Java. The professor presents the following code, and claims the code will create fractions such as 1/6, 2/6, etc. (I added main() so it can be tested.)
public class Test {
public static void main(String[] args) {
Fraction[] f = new Fraction[5];
for (int i=0; i<5; i++){
f[i] = new Fraction(i, 6);
}
}
}
I am testing this in Eclipse, obviously the code does not compile since there is no class Fraction, and even if I change Fraction to double the code still will not produce any fractions.
I am guessing the professor intended to write this:
public class Test {
public static void main(String[] args) {
double[] f = new double[5];
for (int i=0; i<5; i++){
f[i] = (i/6);
}
}
}
Is my reasoning correct?
Source: https://www.youtube.com/watch?v=wGibp2L5uCc #12:25
First of all, note that this will start at 0/6, not 1/6. Second of all, the professor is most probably referring to a hypothetical Fraction class that stores exact fractions (i.e. a numerator and a denominator as two ints); a double cannot do this.
Now, if you want to use doubles (which will not store exact fractions per se but rather the approximate numbers they represent), you have to use double division (and not integer division, as you are currently performing):
f[i] = i/6.0;
As #StephenTG points out, the Fraction class seems to be implemented here.
Yes and no. This:
f[i] = new Fraction(i, 6);
Means
Store on position i of the f array, this fraction object
f is a Fraction[], meaning that each index contains a Fraction typed object. You need to create a new one (i.e. new Ftaction(1,6)) in order to store 1/6. You were right about what to store, you just were not getting the whole picture about how do you represent it.
Just for the sake of your class, I assume that Fraction is a type created by your teacher and that you have to include in your project (As others have correctly suggested, you might be searching for this class)
There is fraction class here:
http://www.cs.berkeley.edu/~jrs/61bf98/labs/lab2/Fraction.java
I assume this is part of your class as well.
You have to download this file and add it to your project.
Well, if the Fraction class has a method to return a double or a float, it can be very well constructed with int actually.
Then the internal logics will take care of processing and returning the correct type.
Consider this example:
public static void main(String[] args) {
System.out.println(new Fraction(1, 6).getFraction());
}
static class Fraction {
private float fraction;
public Fraction(int num, int den) {
// TODO check that den != 0, otherwise we're in a world of trouble :D
fraction = (float) num/den;
}
public float getFraction() {
return fraction;
}
}
Output:
0.16666667
You need to create the Fraction class in order to create an array of Fraction objects.
From StephenTG's comment, it looks like you need to import Fraction.java into eclipse.
(This Fraction.java has a main method for testing purposes. You can place your code in that method, or you need to remove that method if you want to use your own main method.)
You should define a Fraction class first:
public class Fraction
{
int numerator;
int denominator;
public Fraction(){}
/* watch out for a division by zero Exception!
* maybe throw a custom exception here
*/
public Fraction(int n, int d){
numerator = n;
denominator = d;
}
public float getValue(){
return numerator * 1.0f/denominator;
}
}
your first snippet will only make sense if your Fraction class has a constructor that takes two integer values (e.g.):
class Fraction
{
private int val1, val2;
public Fraction(int val1, int val2)
{
this.val1 = val1;
this.val2 = val2;
}
}
For your second part of the question, your loop will first return an integer and then type-cast it to double. So, the result in your case will always be zero, even though you know it shouldn't. To fix this, any of the following two lines of code will do.
f[i] = ((i + 0.0)/6);
or
f[i] = (i/6.0);