# Überladen von Methoden



## Thisor (27. Dez 2015)

Hey,

ich soll eine Funktion schreiben, welche den Absolutwert einer Zahl zurückliefert:

```
public static double absZahl(double x) {

        double a = Math.abs(x) ;

        return a;
    }
```
Die Funktion soll ich überladen für double, float, int, short und long.
Was und wie überlade ich eine Methode?

EDIT:
Ah, ich kann den Methodennamen weiter benutzen, aber der Datentyp muss verändert werden...?
Wie ist das denn beim aufrufen? Dann rufe ich doch quasi mit absZahl(double x) 5 Methoden gleichzeitig auf, oder?


----------



## javampir (27. Dez 2015)

nein, der aufruf bestimmt sich dann durch den datentyp des übergebenen parabeters.
absZahl(5) ist ja was anderes als absZahl(5.0)


----------



## Thisor (27. Dez 2015)

jaa, stimmt! 
also mein Code: 

```
public static double abs(double x) {

        double a = Math.abs(x);

        return a;
    }

    public static int abs(int x) {

        int b = Math.abs(x);

        return b;
    }

    public static short abs(short x) {

        short c = Math.abs(x);

        return c;
    }

    public static long abs(long x) {

        long d = Math.abs(x);
       

        return d;
    }

    public static float abs(float x) {

        float e = Math.abs(x);

        return e;
    }
```
sieht etwas einfallslos aus  aber es funktioniert^^'
also wenn ich es richtig verstanden habe, bedeutet eine Methode zu überladen, dass ich denselben Namen benutzen kann und andere Dinge damit anstellen kann, aber der Datentyp am Methodenkopf und! der Parameter müssen ein anderen Datentyp haben (damit es überhaupt sinn macht ?).

btw: beim short zeigt mir das programm einen Fehler an, dass ich es doch casten soll.  Warum?


----------



## javampir (27. Dez 2015)

der Rückgabewert kann auch gleich sein.
bei short sollst du wahrscheinlich casten, weil es eventuell keine short abs(short) in math gibt


----------



## Thisor (27. Dez 2015)

Ich möchte bzw muss diese Methoden nun in einer anderen Klasse in der Main-Methode aufrufen.
abs(); funktioniert nicht..und google gibt mir zu komplexe beispiele an
Wie rufe ich sie denn auf?


----------



## javampir (27. Dez 2015)

static methoden: klassenname.methodenname


----------



## Thisor (27. Dez 2015)

also dann 

```
Mathematics.abs(x);
```
 in meinem Fall. Bekomme jedoch eine Fehlermeldung mit "x cannot be resolved to a variable".


----------



## javampir (27. Dez 2015)

naja, x scheint es eben nicht zu geben.


```
int x = 5;
Mathematics.abs(x);
```


----------



## Thisor (27. Dez 2015)

Doch, x wird ja sogar durchgehend in den Parametern eingegeben... Und dann musste ich noch mit JUnit drüber gehen und blaaah x müsste also schon initialisiert sein


----------



## JCODA (27. Dez 2015)

Dann poste doch deinen Code! ... Es könnte viel schneller jemand helfen, wenn man weiß, was du falsch machst, anstatt raten zu müssen.


----------



## Thisor (30. Dez 2015)

Sorry, war unterwegs.
Hier der code, allerdings habe ich diese Klasse nicht geschrieben sondern wurde uns so gegeben:


```
RunWith(JUnitParamsRunner.class)
public class MathematicsTest {

    static Object[] absValues() {
        return new Object[] {
                new Object[] {  1, 1 },
                new Object[] { -1, 1 },
                new Object[] {  0, 0 },
        };
    }

    @Test
    @Parameters(method = "absValues")
    @TestCaseName("abs((double) {0}) sollte {1} sein")
    public void testAbsDouble(double x, double expected) throws Exception {
        Class<Mathematics> cl = Mathematics.class;
        Method m = check(cl, "abs", Double.TYPE, Double.TYPE);
        assertEquals((double) expected, (double) m.invoke(cl, x), 0.01);
    }

    @Test
    @Parameters(method = "absValues")
    @TestCaseName("abs((int) {0}) sollte {1} sein")
    public void testAbsInt(double x, double expected) throws Exception {
        Class<Mathematics> cl = Mathematics.class;
        Method m = check(cl, "abs", Integer.TYPE, Integer.TYPE);
        assertEquals((int) expected, (int) m.invoke(cl, (int) x));
    }

    @Test
    @Parameters(method = "absValues")
    @TestCaseName("abs((short) {0}) sollte {1} sein")
    public void testAbsShort(double x, double expected) throws Exception {
        Class<Mathematics> cl = Mathematics.class;
        Method m = check(cl, "abs", Short.TYPE, Short.TYPE);
        assertEquals((short) expected, (short) m.invoke(cl, (short) x));
    }

    @Test
    @Parameters(method = "absValues")
    @TestCaseName("abs((long) {0}) sollte {1} sein")
    public void testAbsLong(double x, double expected) throws Exception {
        Class<Mathematics> cl = Mathematics.class;
        Method m = check(cl, "abs", Long.TYPE, Long.TYPE);
        assertEquals((long) expected, (long) m.invoke(cl, (long) x));
    }

    @Test
    @Parameters(method = "absValues")
    @TestCaseName("abs((float) {0}) sollte {1} sein")
    public void testAbsFloat(double x, double expected) throws Exception {
        Class<Mathematics> cl = Mathematics.class;
        Method m = check(cl, "abs", Float.TYPE, Float.TYPE);
        assertEquals((float) expected, (float) m.invoke(cl, (float) x), 0.01);
    }
```


----------



## Saheeda (30. Dez 2015)

Und wo in der Testklasse bekommst du die Fehlermeldung "x cannot be resolved to a variable"?

IMHO ist die Testklasse ziemlich seltsam und unnötig kompliziert geschrieben.
Ein einfacher Unit-Test sähe so aus:


```
@Test
    public void testAbsDouble() throws Exception {
        assertEquals(1.0, Mathematics.abs(1.0), 0.01);
   }
```
Oder so, wenn man das lesbarer findet:

```
@Test
    public void testAbsDouble() throws Exception {
        double expected = 1.0;
        double actual = Mathematics.abs(1.0);
        double delta= 0.01;
        assertEquals(expected, actual, delta);
    }
```


----------



## Thisor (30. Dez 2015)

Die Fehlermeldung kommt in der neuen Klasse, wenn ich sie aufrufen mag 


Saheeda hat gesagt.:


> Code (Java):
> @test
> *public* *void* testAbsDouble() *throws* Exception {
> assertEquals(1.0, Mathematics.abs(1.0), 0.01);
> }


So schreibe ich meine Tests auch 
Die TestKlasse ist von nem Prof geschrieben
Lg


----------



## Saheeda (30. Dez 2015)

Also nicht in der Testklasse? Dann zeig doch bitte mal die ganz konkrete Methode/Klasse, in der du diesen Fehler bekommst. "x cannot be resolved to a variable" heißt auf deutsch schlicht: Gibts nicht, Variable wurde nirgendwo deklariert.


----------



## Thisor (31. Dez 2015)

Ich muss die Methode in einer neuen Klasse aufrufen, also:

```
public class Math_Main {

    public static void main(String[] args) {

    Mathematics.abs(x);

       
    }
}
```

x ist in der Tat nicht deklariert/initialsiert in der neuen Klasse, genau genommen in keiner der Klassen, zumindest nicht von mir. Ich gehe nur davon aus das sie in der TestKlasse initialisiert worden ist, da ich mit dem Parameter x arbeite. Und in x muss ja was drin sein, sonst würde es mir ja Fehler in den Tests zeigen.


----------



## JStein52 (31. Dez 2015)

x muss in dem Scope deklariert sein wo du es verwendest und nicht irgendwo !!
Also in deinem Beispiel in main !! Und der Parameter in deiner Methode kann ja durchaus auch x heissen, hat aber nichts mit dem x zu tun das undefiniert ist !


----------



## Thisor (31. Dez 2015)

Scope bedeutet Klasse?
Wenn ich dann in der neuen Klasse die Methode aufrufe, kann ich dann gar nicht mit den Werten arbeiten bzw auch aufrufen?
Dann bin ich ja quasi gezwungen das x neu zu initialsieren und die davorigen Methoden bringen mir ja rein gar nichts. Zumindest ist das aufrufen der Methode in einer neuen Klasse irgendwie sinnfrei in dem Fall. Wenn ich also was komplexes ausrechnen wollen würde, in einer anderen Klasse, nur damit die MainKlasse schön aussieht, kann ich sie ja nicht in der neuen Klasse aufrufen, da die Werte, die in der Variable eingespeichert werden, gar nicht weiter gegeben werden "können". Also in dem Fall zumindest.
Die Aufgaben sind ja ohne Veerbung bzw get/set bzw add/poll.
Richtig?


----------



## JStein52 (31. Dez 2015)

Der Parameter mit dem du eine Methode aufrufst (in deinem Fall x) muss halt an der Stelle bekannt sein wo du die Methode aufrufst !! Und mit deinem Sprachgebrauch tue ich mich etwas schwer, aber wenn du nun den Wert mit dem du die Methode aufrufen willst in der main-Methode hast du möchtest aber nicht dort deine Mathematics.abs(x);  aufrufen sondern in einer anderen Methode einer anderen Klasse dann musst du den Wert halt dieser anderen Methode aus main wiederum als Parameter mitgeben !!


----------



## Saheeda (31. Dez 2015)

@Thisor
Scope bedeutet Gültigkeitsbereich. Jede Klasse, jede Methode und jeder Block beschreibt einen solchen. Alles, was innerhalb eines Scopes definiert wird, ist innerhalb dessen gültig, aber nicht außerhalb. Es gibt in Java keine global definierten Variablen (wie z.B. in JavaScript).
http://www.java-made-easy.com/variable-scope.html
http://openbook.rheinwerk-verlag.de...02_004.htm#mjb044d5eb156360a6192e0bde3eeaceb0

Die TestKlasse soll keine Werte bereitstellen, sondern validieren, dass die Methoden so funktionieren, wie erwartet. Das Programm an sich läuft ohne TestKlassen, vollkommen autark.

Bei komplexeren Berechnungen gibt es meistens eine "Startmethode", welche Teilaufgaben an andere Klassen/Methoden delegiert. Es kann durchaus passieren, dass ein Wert durch mehrere Klassen einfach nur durchgereicht wird, bis mit ihm tatsächlich gerechnet wird.


----------



## Thisor (31. Dez 2015)

@JStein52 die Aufgabe verlangt dass ich die Methode in einer neuen Klasse aufrufe, dann geht das gar nicht oder wie, wenn der Parameter in der neuen Klassen gar nicht bekannt ist? Gibt es denn eine Möglichkeit den Parameter direkt anzusprechen, außerhalb der Klasse wo sie initialsiert worden ist?
Also, wie gebe ich denn die Parameter mit in die neue Klasse?

@Saheeda aber es gibt doch zum Beispiel extends und implements, womit ich variablen weiter veerben kann zum Beispiel.

Dass das Programm auch ohne die Testklasse funktioniert ist mir schon bewusst, aber durch die Testklasse wird ja überprüft ob das Ergebnis richtig ist. Und es werden ja dann gewisse Werte erwartet, da ich aber jetzt in diesem Programm x nicht selbst initialsiert habe, es aber in die Parameter eingeben kann, und somit gewisse und verschiedene Auswertungen stattfinden, bedeutet das doch, dass irgendwo x initialsiert worden ist, oder nicht? 

Und zum letzten Punkt, damit ich einen Wert durch mehrere Klassen durchreichen kann, müssen die Werte doch vererbbar sein, aber hier arbeite ich doch ohne Veerbung. Geht das trotzdem?


----------



## Saheeda (31. Dez 2015)

@Thisor
Bei dir ist so einiges durcheinander geraten.




> die Aufgabe verlangt dass ich die Methode in einer neuen Klasse aufrufe, dann geht das gar nicht oder wie, wenn der Parameter in der neuen Klassen gar nicht bekannt ist?


Im Test passiert es durch diesen Aufruf: "m.invoke(cl, x)". Du übergibst den Wert x von der Testklasse hinüber in die Mathematics-Klasse.



> aber es gibt doch zum Beispiel extends und implements, womit ich variablen weiter veerben kann zum Beispiel.
> [...]
> Und zum letzten Punkt, damit ich einen Wert durch mehrere Klassen durchreichen kann, müssen die Werte doch vererbbar sein, aber hier arbeite ich doch ohne Veerbung. Geht das trotzdem?


"extends" erweitert eine Klasse, d.h. du fügst zusätzliches Verhalten hinzu. "implements" definiert eine Klasse, welche ein Interface erfüllt.
Beide Schlüsselwörter haben mit dem Durchreichen von Variablen absolut nichts zu tun. Variablenübergabe erfolgt durch Methodenaufrufe.

Das hier wäre ein stark vereinfachtes Beispiel zum Durchreichen von Werten. Der Initiale Aufruf erfolgt in doSomething(), mit den Werten gearbeitet wird aber erst in calculate(). Die Methode dazwischen reicht den Wert nur weiter und könnte z.B. noch überprüfen, ob die Werte innerhalb gewisser Grenzen liegen, o.ä (was sie hier nicht tut, aber könnte).

```
private void doSomething() {      
        int a = 1;
        int b = 2;
        int sum = doOther(a, b);
    }
  
    private int doOther(int a, int b) {
        return calculate(a, b);
    }
  
    private int calculate(int a, int b){
        return a + b;
    }
```





> Und es werden ja dann gewisse Werte erwartet, da ich aber jetzt in diesem Programm x nicht selbst initialsiert habe, es aber in die Parameter eingeben kann, und somit gewisse und verschiedene Auswertungen stattfinden, bedeutet das doch, dass irgendwo x initialsiert worden ist, oder nicht?



Sobald das Programm in Betrieb genommen wird ("Run"), müssen natürlich die Werte initialisiert werden, beispielsweise in einer main-Methode. Dort musst du dann eben definieren, dass es eine Variable "int x = 5" oder wie auch immer gibt.



Schau dir bitte nochmal die Grundlagen zu Methoden, Parametern und Variablen an, du wirst sonst bei den nächsten Tutorien nicht froh.


----------



## Thisor (1. Jan 2016)

Oh hm..damn!
Was genau ist mit einem "Verhalten" gemeint?

Und mal so aus neugier, wann brauch ich denn mal leere Blöcke, leere Anweißungen oder einfach nur 

```
;
```
? 
Und was ich noch nicht ganz so verstehe, wenn ich variable initialisiere, dann gelten die doch nur innerhalb diesem scope. Ist aber nicht quasi eine Methode jeweils ein scope? Also kann ich jede Variable benutzen die einmal (zumindest in der selben Klasse) definiert worden ist und sie dann von Methode zu Methode durchreichen? 



Saheeda hat gesagt.:


> Sobald das Programm in Betrieb genommen wird ("Run"), müssen natürlich die Werte initialisiert werden, beispielsweise in einer main-Methode. Dort musst du dann eben definieren, dass es eine Variable "int x = 5" oder wie auch immer gibt.


in dem Fall wird es ja mit 

```
m.invoke(cl, x)
```
 initialisiert. Also muss ich nichsdestotrotz die Variable (also x) in der neuen Klasse neu initialiseren?


----------



## Saheeda (1. Jan 2016)

Meistens sind das zusätzliche Methoden, je nach Anwendungsfall können das aber auch Instanzvariablen sein.

Was meinst du mit leeren Blöcken bzw. wie kommst du darauf? Ein Block wird in Java durch die spitzen Klammern ({}) begrenzt. Leere Blöcke sind relativ sinnfrei und einige IDEs lassen sich so einstellen, dass leere Blöcke als "Bad Code" angekreidet werden.


Ja, jede Methode bildet/hat einen eigenen Scope. Du kannst Variablen von Methode zu Methode übergeben (auch über Klassen hinweg), aber nicht einfach so:


```
private void doOther() {
//a wird im Scope von doOther deklariert und initialisiert.
        int a = 0;      
}
  
private void doSomething() {
//im Scope von doSomething existiert a nicht, deswegen gibts Compiler-Fehler.
        a = 5;
}
```
Der entscheidende Punkt ist aber nicht die Initialisierung, sondern die Deklaration (wenn du den Unterschied nicht kennst --> google). Der Ort der Deklaration bestimmt den Scope.


"m.invoke" ist weder eine Initialisierung noch eine Deklaration, sondern ein Methodenaufruf.


Bevor du dich mit Vererbung und Interfaces beschäftigst, schau dir wirklich nochmal die absoluten Grundlagen an; auch, was Begriffe wie Initialisierung, Deklaration, Aufruf und Übergabe angeht, sonst reden wir ständig aneinander vorbei.


----------



## Thisor (1. Jan 2016)

Habe mir jetzt nicht alles durchgelesen(werd ich heute Abend noch, gibt gleich Fondue ), aber zu dem Absatz hier


Saheeda hat gesagt.:


> Bevor du dich mit Vererbung und Interfaces beschäftigst, schau dir wirklich nochmal die absoluten Grundlagen an; auch, was Begriffe wie Initialisierung, Deklaration, Aufruf und Übergabe angeht, sonst reden wir ständig aneinander vorbei.



Also Initialisierung ist soviel ich weiß nichts weiter als ein Wert einer Variable zuzuweißen.
Bsp:
	
	
	
	





```
int x = 5;
```
Dekleration ist einfach eine variable zu "deklarieren" (ich weiß, ist nicht so optimal ein wort mit sich selbst zu erklären) also quasi: 

```
int x;
double z;
//usw
```
Aufruf und Übergabe, was zumindest die Definition ist, haben wir nicht ausführlich besprochen. Aber arbeiten bereits damit. Somit ist es sehr gut möglich das mein Sprachgebrauch sehr verwirrend sein kann, wenn sie nicht bereits ist (wie bereits von JStein52 erwähnt ). Wir haben bisher ausschließlich nur Methoden aufgerufen ( zumindest in Programmieren 1, also Programmieren ohne Objekte). Und ich habe das bisher so verstanden das man eine Methode hat, die was macht, und diese Methode kann man dann in der Main "aufrufen". Sprich in der console ausgeben lassen, oder eben die Methode in der Main-Methode festhalten, mehr kann ich mit dem Begriff  "Aufruf" momentan nicht anfangen. Vielleicht auch weil wir mit dem Stoff nicht weiter sind.

(Vielleicht sollte ich noch dazu erwähnen, dass mit Methoden Funktionen gemeint sind. Also ich weiß, dass zum Beispiel System.out.println oder Math.round auch Methoden sind, aber ich meine jetzt hauptsächlich KlassenMethoden..vllt hätte ich das dazu sagen sollen).


Zu Übergabe kann ich nichts weiter sagen als bereits das Wort an sich schon sagt, ich würde behaupten, das heißt so viel wie Werte in Klassenmethoden zu übergeben.

Zu Interfaces und Veerbungen kann ich dir leider nur zustimmen, da muss ich glaub nochmal so richtig bei 0 anfangen..


----------



## Thisor (3. Jan 2016)

Sodale, 
also das ich jetzt die Methode aufrufen abs aufrufen kann, muss ich sie mit der Klasse.MethodennameParamenter aufrufen. Aber ohne Initialisierung geht da nichts, nicht mal mit Dekleratio.
Also muss ich die Variable x in dem Fall manuell eingeben.
Aber dann auch in der Klasse wo ich sie aufrufen mag, right?
lg


----------

