What is a good Java design to call through methods? - java

This the following a good design if I wanted to call a method to a method?
The code below is this just an example.
public Enigma(){
String sentences = "This ";
method1(sentences);
}
public void method1(String x){
x = x + "a ";
method2(x);
}
public void method2(String x){
x = x + "test ";
method3(x);
}
public String method3(String x){
x = x + "!";
return x;
}

If those methods are only called from the constructor, then there's no point in making them public.
Also, usually you'd call method1 from the outside after creating the Enigma object.
Finally, as you may know chaining calls like that may lead to code that is difficult to understand and follow.
But if your question is related to "does this work", the answer is simply yes :)

I believe you are on the right track. Even if your example doesn't do anything concrete, I believe it is a good idea to point out possible flaws.
The class name has to be the same name of its Java file. For example, your class "Enigma" has to be written in the "Enigma.java" file. Otherwise, problems can appear. Often it is a good thing to remember.
Note that you can call method3 from method2 in a way that uses the output of this function.
public method2(String x) {
x = x + "a ";
x = x + method3(x)
}
Note that this example is only to show you how you can retrieve the value of the method you just called. You can always simply call this method the same way you call a void even if the method returns something. Both options work, it is for you to decide what your program has to do and how, depending on the context.
Overall, the correct Java syntax for your class is this one:
public class Enigma {
//put your class properties here
public Enigma(){
String sentences = "This ";
method1(sentences);
}
public void method1(String x) {
x = x + "a "; method2(x);
}
public void method2(String x) {
x = x + "test "; method3(x);
}
public String method3(String x) {
x = x + "!";
return x;
}
}
After this, if you are using Enigmaa as an object, you might want to add a constructor. If Enigma is not an object, use static methods by writing static just before your method return type in the declaration. For example: public void method1(String x) { would become public static void method1(String x) {. Doing so when possible is a good way to keep simple a program that acts like a script.

Related

Java method that produces an object

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.

Eclipse extract to method not working for Lambdas

I'm playing around with lambdas in eclipse oxygen. I have code something like this
#FunctionalInterface
interface TriFinction<O,I,J, R> {
R whatEver(O object, I input1, J input2);
}
class Dummy {
public String dothingsWithTwoArgs(String a, String b) {
return a+b;
}
}
public class LambdaTest {
public static void main(String[] args) {
Dummy::dothingsWithTwoArgs;
}
}
I'm unable to extract Dummy::dothingsWithTwoArgs. Eclipse is showing a compilation error Syntax error, insert "AssignmentOperator Expression" to complete Expression, but extraction is working perfectly in intellij. Is there any workaround for this in eclipse?
First notice that your dothingsWithTwoArgs is not static, therefore you should not attempt to invoke it in a static fashion: you should use an instance of your Dummy class or make the dothingsWithTwoArgs static
Here are some illustrations that will get you going
First you need a method that has your TriFinction as one of its parameters
Example:
public static String sumToString(String a,String b, String c, TriFinction<String,String,String,String> f) {
return f.whatEver(a, b, c);
}
Second, in your Dummy class you need a method that matches the genric signature of your TriFinction (which means for example that it receives three parameters for O,J, and I and that it returns a R)
for example
public static String dothingsWithThreeArgs(String a, String b,String c) {
return a+ " " + b + " " + c;
}
Now you can use the method reference in your main method for example:
System.out.println(sumToString("2","3","4",Dummy::dothingsWithThreeArgs));
Here is the full example along with a second illustration from your TriFinction (and I guess you should refactor and rename it TriFunction :) )
public class ExtractWithLambda {
#FunctionalInterface
interface TriFinction<O,I,J, R> {
R whatEver(O object, I input1, J input2);
}
public static String writeEqu(TriFinction<Double,Double,Double,String> f) {
return f.whatEver(2.5, 3.4, 5.6);
}
public static String sumToString(String a,String b, String c, TriFinction<String,String,String,String> f) {
return f.whatEver(a, b, c);
}
public static void main(String[] args) {
System.out.println(writeEqu(Dummy::writeEquation));
System.out.println(sumToString("2","3","4",Dummy::dothingsWithThreeArgs));
}
}
class Dummy {
public static String dothingsWithThreeArgs(String a, String b,String c) {
return a+ " " + b + " " + c;
}
public static String writeEquation(double a, double b, double c) {
return a + "*x*x " + b + "*x " + c ;
}
}
One main thing we should know is Compilation error messages are compiler dependent. This does not mean different compilers would produce different error messages all the time. But there can be situations.
Regarding your problem I found this answer and post. That post has a detailed explanation about this error under topic not a statement.
So the main point is this. As you mentioned, this error message is specific to Eclipse compiler. The point the compiler is raising is your line is just an expression, not a statement. In order to understand it as a statement, the compiler wants you to add an assignment operator. That's the whole meaning of insert "AssignmentOperator Expression" to complete Expression. So what you all want to do is just assign that line to another defined variable, which would look like this.
someVariable = Dummy::dothingsWithTwoArgs;
Hope you can find more depth and more examples with the sources I mentioned. :))
Extracting Lambda to a method seems only suported from Eclipse 4.23 (Feb. 2022, 6 years later)
Extract lambda body to method
A new content assist has been added to extract the body of a lambda to a method.
To invoke the new feature, perform a Ctrl + 1 within the selected lambda body:

Calling a function without doing a new

I wrote a sort function and class in Java:
public class MiscellaneousUtilities {
/**
* Changes a list of "First Last" to "Last, First" and "First Middle Last" to "Last, First Middle", etc.
*/
public static Function<String, String> ToLastFirstFunction = new Function<String, String>() {
#Override
public String apply(String nm) {
String[] nmarr = nm.split(" ");
int last = nmarr.length - 1;
String res = nmarr[last];
if (last > 0) {
res += ",";
}
for (int i = 0; i < last; i++) {
res += " " + nmarr[i];
}
return res;
};
};
}
When I want to use it I can't just say MiscellaneousFunctions.ToFirstLastFunction()
I have to do a new MiscellaneousFunctions().ToFirstLastFunction;
I tried putting static in front of the class declaration but it allows only public, final and abstract. Looking at the Math class if I want to use Math.min() I don't have to do a new Math().min(). Math is also defined as a class that does not have static in front of it, and min() does as does ToFirstLastFunction, so I don't understand the difference.
That's because you have to call that function with an apply like this:
MiscellaneousFunctions.ToFirstLastFunction.apply("yourstring");
You can add an other static function as a shorthand though:
public static String toFirstLast(String str) {
return ToLastFirstFunction.apply(str);
}
The main difference between Math.min and your solution that Math.min is a regular static method while you have a Function object and those can be called with apply.
Math.min() is a a method not a function, declared like this in Math.class:
public int min(int a, int b) {
...
}
... and it is methods like this that you can invoke directly as in int x = Math.min(3,2).
You have created a public static class variable called ToLastFirstFunction -- that's not something you can call like a method. But you can do things with it using the methods in the java.util.function.Function interface -- the simplest being apply():
String out = MiscellaneousFunctions.toFirstLastFunction.apply("John Doe");
(I changed the capitalisation of your identifier -- find out about Java capitalisation conventions)
It is not the case that you can call your public static Function<...> using new MiscellaneousFunctions().toFirstLastFunction("John Doe") -- I'm not sure why you thought it was so.
You can do new MiscellanousFunctions().toFirstLastFunction.apply("John Doe") -- but your compiler should warn you about accessing a static variable via an instance. MiscellanousFunctions.toFirstLastFunction.apply() is the right way.
So the short answer to your question is: if you want to invoke it that way, write it as a method.
But if that's the case, why would you define an operation as a function, rather than a method?
Well, functions have the benefit that, unlike methods(*), they are objects -- so you can pass them around, put them in collections, assign them to variables. And they have methods like compose() and andThen() which return a new function that combines this function with another.
So you can do things like:
Map<String,Function<String,String> nameTranslationStrategies = new HashMap<>();
nameTranslationStrategies.put(
"no change", x -> x);
nameTranslationStrategies.put(
"to first-last",
MiscellaneousFunctions.toFirstLastFunction);
nameTranslationStrategies.put(
"capitalised first-last",
MiscellaneousFunctions.toFirstLastFunction
.andThen( s -> s.toUpperCase());
...
String nameTranslationOption = config.getProperty("nameTranslationOption");
String name = nameTranslationStrategies
.get(nameTranslationOption)
.apply(inputString);
Java programmers managed for decades without this feature -- functions didn't exist until Java 8. But you can do lots of neat things with them.
Even so, this isn't a reason to write your code as a Function bound to a static variable, since you can access ordinary methods as functions using the :: syntax:
Function<Double,Double> logarithm = Math::log;
double x = logarithm.apply(2.0);
Note also, that you've used a long-winded syntax to define your function:
public static Function<String, String> slimify = new Function<String, String>() {
#Override
public String apply(String s) {
return "slim says " + s;
}
}
... can be written as:
public static Function<String,String> slimify = s -> {
return "slim says " + s;
}
... or even (since this one's a one-liner)
public static Function<String,String> slimify = s -> "slim says " + s;
It's good to know the long-winded way, because it shows how functions work behind the scenes. But in real world code, the shorter form is the way to go, as it is more expressive: the intent of the code isn't hidden by clutter. This is such a quick and easy way of expressing a function, that people often use them in-line rather than assign them to a variable -- as I have done in the map example above.
(*) I said that methods are not objects. This isn't strictly true -- partly because you can get one as an object using ::, but also because you can use Java's Reflection API to access classes and methods as objects. But you don't want to use Reflection, unless you really know you need to.
Math.min() is a public static method called min, your Function is a Function object, it's not a method. Your object has a method apply and you have to use that method for what you want to achieve, like this:
MiscellaneousFunctions.ToFirstLastFunction.apply(something)

Java CLASS METHODS

CLASS METHODS question: According to D. Flanagan, Java in a Nutshell, 5 edn, pg 102-103, CLASS methods are allowed to be invoked FROM EITHER i) code existing OUTSIDE of the method's class, the standard paradigm, OR from ii) INSIDE the class itself which defines the class method. Here, I believe the standard oo programming paradigm is to put System.out.println statements in a class T method prt(), and then declare a new T object, t1 say, with t1.prt() method called from the outside class, main:
class T {
int x = 4, y = 5;
public static void prt(int x0, int y0) {
System.out.println("T class ending: x= " + x0 + ", y=" + y0);
}
// <---- this is where an extra statement gets inserted
}
class S extends T {
int m = 10;
int n = m + x + y;
public void prs() {
System.out.println("S subclass ending: m = " + m + ", n=" + n);
}
}
public class A {
public static void main(String[] args) {
System.out.println("****Program start");
System.out.print("main method: ");
T t1 = new T();
t1.prt(3, 4);
S s1 = new S();
System.out.println(s1.m);
System.out.println(s1.n);
s1.prs();
System.out.println("****Program ending");
}
}
However, when I demand to do what Flanagan states is possible, to invoke a class method FROM WITHIN the class T in which the CLASS METHOD is defined, I get the original compilation error again, that "an identifier is expected." That is, inserting the following statement at the end of class T code, as shown above(*), gives a compiLe error:
T.prt(3,4);
Why this is an error? My question asks about general CLASS METHODS, not a special class method, namely a constructor, though the Java reference text I'm citing does deal with CLASS METHODS in general. Am I missing something obvious? My sincerest gratitude, Richard Pan in Newark
That is, inserting the following statement at the end of class T code, as shown above(*), gives a compiLe error:
You can only write code inside methods. Outside methods you can only define fields, which is what it is expecting.
Am I missing something obvious?
I used my IDE to format the code (This was one key press btw) and the problem became obvious. If you don't format your code it make it harder to read and understand.

No output In Eclipse for a simple java program

I think I have written this program pretty well. It gives me no errors, but it is not giving me any output either. What is wrong with this? I checked other programs to see if anything is wrong with Eclipse, but every other program is running except this.
Note: I am newbie Java learner. Explain the problem in detail. I know I have written the spelling of Inheritance wrong.
public class Inheritence {
int a;
String b;
Inheritence(int x, String y) {
a = x;
b = y;
}
}
class B extends Inheritence {
int c;
B(int j, String k, int l) {
super(4, "Srimanth");
a = j;
k = b;
c = l;
}
public static void main(String args[]) {
Inheritence obj1 = new Inheritence(4, "Srimanth");
B obj2 = new B(4, "Srimanth", 5);
System.out
.println("The details of the guy are" + obj1.a + " " + obj1.b);
System.out.println("The details of the guy are" + obj2.c);
}
}
The error in your code is that main method is defined in a non public class B . Move main method to public class Inheritence or define make class B subclass of Inheritence and Inheritence having main method.
The name of the file is Inheritence.java?
In that case you should put different classes in different files, and call the one that have the main method (better write the parameters like "String[] args") probably can't find the main method
When I run it I get the following:
error: Class names, 'Inheritence', are only accepted if annotation processing is
explicitly requested
1 error
Try the changing the file name/class name.

Categories