# Java Klassen "überschreiben"



## Nova (3. Aug 2006)

Problem:
Wie in einem anderen Thread geschildert verbietet es Java beim Drucken Papiergrößen anzugeben die breiter als lang sind.
Technisch ist dies aber kein problem, andere Programme können das ja auch.

Das Problem ist die Klasse MediaSize (Package javax.print.attribute.standard), bzw. die Konstruktoren.
Beispiel:

```
public MediaSize(float x, float y,int units, MediaSizeName media) {
	super (x, y, units);
	if (x > y) {
	    throw new IllegalArgumentException("X dimension > Y dimension");
	}
	mediaName = media;
	mediaMap.put(mediaName, this);
	sizeVector.add(this);
    }
```

Das Problem ist die if-Abfrage nach "x > y".
Ich habe die Abfrage mal auskommentiert und die Klasse i8m JRE mit der modifizierten ersetzt.
=> Ich kann jetzt problemlos Papiergrößen angeben die breiter als lang sind und gedruckt wird auch korrekt.

Es ist also scheinbar eine willkürliche Einschränkung vom Programmierer?!?


Es ist natürlich keine Lösung das JRE zu modifizieren da man das ja dann auf jedem Rechner machen müsste auf dem die Software läuft, daher die Frage:
Kann ich Java dazu bringen meine MediaSize Klasse zu nehmen statt die aus dem JRE?

(Ich habe einen neuen Thread aufgemacht da dies ja nichts direkt mit dem Drucken zu tun hat sondern allgemein mit Java/dem JRE)


mfg
Christian


----------



## Leroy42 (3. Aug 2006)

Es kommt darauf an:

Du kannst deine eigene Klasse von MediaSize überschreiben und diese benutzen.

Allerdings hast du keine Möglichkeit, _nicht eigene Klassen, _davon zu überzeugen,
deine neue MediaSize zu nehmen.


----------



## SlaterB (3. Aug 2006)

es geht schon, sofern diese 'nicht eigenen Klassen' eine entspechende Möglichkeit direkt anbieten, etwa
setMediaSize(MediaSize ms);

oder indem sie ein solches Objekt vom User benötigen, z.B.
printDocument(Document doc) // dann könnte man eine Unterklasse von Document benutzen

aber das ist natürlich nur selten der Fall, in deinem Umfeld anscheinend nicht, 
wobei ich natürlich überhaupt nicht weiß worum es geht


----------



## Nova (3. Aug 2006)

@Leroy72:
Du meinst von MediaSize erben?
Das geht leider nicht da mediaMap und sizeVektor private static sind welche ich nicht überschreiben kann und ich den Super-Superkonstruktor aufrufen (Size2DSyntax) müsste um die breite und länge zu speichern was ebenfalls nicht möglich ist.

Die Klasse wird irgendwann irgendwo beim drucken von Java aufgerufen (keine Ahnung wo), also von einer "nicht-eigenen Klasse" wie du es nennst.


mfg
Christian


----------



## Nova (3. Aug 2006)

SlaterB hat gesagt.:
			
		

> es geht schon, sofern diese 'nicht eigenen Klassen' eine entspechende Möglichkeit direkt anbieten, etwa
> setMediaSize(MediaSize ms);
> 
> oder indem sie ein solches Objekt vom User benötigen, z.B.
> ...



Ich rufe "new MediaSize(156.0f, 101.5f, MediaSize.MM, MyMdiaSizeName.TEST)" auf.
Damit wird dem Papierformat-Namen "MyMediaSizeName.TEST" die Größe 156x101,5mm zugewiesen.

Beim drucken übergebe ich dann den Papiernamen (man kann nicht direkt die Papiergröße angeben) und drucke mit:

```
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
    aset.add(MyMediaSizeName.TEST);
    printJob.print(aset);
```

Irgendwann ruft Java dann wohl "MediaSize.getMediaSizeForName(MyMediaSizeName.TEST)" auf um an das Papierformat zu kommen. (das rote ist wohl das Problem, denn das ist vermutlich in irgendeiner JRE-Klasse hardcodiert).


----------



## Mario_H (3. Aug 2006)

Na und wenn du die Klasse in der du:



> ```
> public MediaSize(float x, float y,int units, MediaSizeName media) {
> super (x, y, units);
> /*if (x > y) {
> ...



gefunden hast überschriebst (also extends), dann nimmste einfach den Code der oben steht,
oder kann man die Klasse nicht überschreiben?
(Bin mir grad nicht sicher worauf du dich bezogen hast, als gesagt hast, könne man nicht überschreiben.)


----------



## Nova (3. Aug 2006)

Doch, man kann von dieser Klasse erben, aber dann rufe ich mit

```
super(x,y,unit);
```
ja den Konstruktor von MediaSize auf welche die Exception wirft, ich müsste schon sowas wie

```
super.super(x,y,unit)
```
schreiben was aber nicht geht.

Außerdem muss ich dann eigene mediaSize, mediaMap und sizeVektor Objekte erstellen da die private sind und desshalb nur direkt in der Klasse MediaSize geändert werden können, bei eigenen Variablen weiß die original MediaSize Klasse dann aber nix und wenn Java dann "MediaSize.getMediaSizeForName(MyMediaSizeName.TEST)"
aufruft ist der name "MyMediaSizeName.TEST" unbekannt...


----------



## Mario_H (4. Aug 2006)

Stimmt. Na dann überschreibste halt die super-class.
Wie ich das sehe hast du den Code der Fehlerhaft arbeitenden Klasse, nimm doch exakt den selben nur dass du  x > y weg lässt und überschreibe damit deren Oberklasse.


----------



## Murray (4. Aug 2006)

Kannst Du nicht im Querformat drucken? Also die Größe so einstellen, wie es MediaSize verlangt


			
				API-Doc hat gesagt.:
			
		

> Class MediaSize is a two-dimensional size valued printing attribute class that indicates the dimensions of the medium in a portrait orientation, with the X dimension running along the bottom edge and the Y dimension running along the left edge. Thus, the Y dimension must be greater than or equal to the X dimension.


und dann die Orientierung entsprechend setzen:

```
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
    aset.add(MyMediaSizeName.TEST);
    aset.add(OrientationRequested.LANDSCAPE);
    printJob.print(aset);
```


----------



## Mario_H (4. Aug 2006)

Ist doch Endlospapier.. (s. oben)


----------



## Nova (4. Aug 2006)

Mario_H hat gesagt.:
			
		

> Stimmt. Na dann überschreibste halt die super-class.
> Wie ich das sehe hast du den Code der Fehlerhaft arbeitenden Klasse, nimm doch exakt den selben nur dass du  x > y weg lässt und überschreibe damit deren Oberklasse.



Hab ich auch schon versucht, aber die Klasse wird dann ja nicht verwendet da Java ja immer "MediaSize.blabla" aufruft und nicht meine modifizierte Klasse.
Der Aufruf versteckt sich wohl in "PrinterJob", dieses Objekt wird aber dynamisch erstellt (weil Plattformabhängig) mit "PrinterJob.getPrinterJob()" und kann daher auch nicht von mir modifiziert werden. Für Windows wird folgende Klasse verwendet von der ich aber keinen Quellcode finde: "sun.awt.windows.WPrinterJob"


Querformat geht leider nicht da es sich um "Endlospapier" handelt, sprich die Paketscheine sind an der langen Seite miteinander verbunden (nicht wie bei DinA4 Endlospapier, da sind ja die kurzen Seiten miteinander verbunden).
(Querformat heißt ja das um 90° gedreht gedruckt wird OHNE das Papier zu drehen)



mfg
Christian


----------



## SlaterB (4. Aug 2006)

Nova hat gesagt.:
			
		

> Doch, man kann von dieser Klasse erben, aber dann rufe ich mit
> 
> ```
> super(x,y,unit);
> ...



den super-Aufruf machst du mit (0,0,0) oder irgendwelchen anderen Dummy-Werten,
was der Konstruktor dann macht ist egal solange er nur keine Exception wirft,
alle privaten Attribute von MediaSize sind ebenso egal,

alle relevanten Operationen, die gebraucht werden musst du überschreiben, praktisch ja nur aus der Vorlage kopieren,

mit statischen Variablen und Operation wird das aber nicht gehen, weiß nicht was da mit MyMediaSizeName.TEST los ist,
wie gesagt: wenn das Überschreiben nicht unterstützt wird (z.B. durch dynamische Objekt-Aufrufe statt statische Klassen-Aufrufe), dann kann man Pech haben

andererseite: was haben diese statischen Dinge mit x und y zu tun? da wird doch wohl nicht eine statische Variable neu gesetzt?


```
Stimmt. Na dann überschreibste halt die super-class.
```
das würde nicht funktionieren wenn ein Objekt vom Typ MediaSize benötigt wird,


----------



## Nova (4. Aug 2006)

Sowas hab ich auch schon versucht, aber durch anlegen von Variablen mit gleichem Namen überschreibe ich ja nicht die Variablen in der Superklasse, sondern überdecke die nur.
Java verwendet als Objekt "MediaSize" und sieht und verwendet daher die "original" Variablen und Methoden und nicht meine, oder hab ich da einen Denkfehler? (Hatte das mal ausprobiert, aber da wurden die zuerst an den Konstruktor übergebenen Werte genommen und nicht meine in den "überschriebenen" Variablen).


----------



## Mario_H (4. Aug 2006)

Oh, klar. Super-class bringt nichts.
Aber das hört sich doch gut an, der Konstruktor kann auch nicht mehr als die ihm übergeben Werte irgendwo hin schreiben. Meinetwegen vorher noch irgendwas berechnen, aber wenn du den Source hast kannste ja wie gesagt den super-Konstruktor (also MediaSize) mit Werten die funktionieren füttern und danach, alles was der Konstruktor mit diesen Werten gemacht hat, korriegieren.

Hast ja den Source, nachschauen was er damit macht, und das hinterher mit deinen Werten nachmachen.


----------



## Nova (4. Aug 2006)

Siehe meinen Post von eben (hat sich scheinbar mit deinem überschnitten)

Kann man eigentlich solche unnötigen Einschränkungen irgendwie an Sun melden das die sich das mal anschauen und ggf. bei späteren Versionen korrigieren?


Da sich die Threads jetzt leider doch irgendwie überschneiden (sorry), hier der Link zum anderen Thread:
http://www.java-forum.org/de/viewtopic.php?t=35030


----------



## Mario_H (4. Aug 2006)

Ja, überschnitten.


Sprichst du hiervon?


```
public class main_clazz
{
	public static void main(String[] args)
	{
		Test1 a = new Test2();
                                System.out.println(a.getStr());
	}
}

class Test1
{
 String getStr()
 {
  return "Test1";
 }
}

class Test2 extends Test1
{
 String getStr()
 {
  return "Test2";
 }
}
```


Ausgabe: Test2


Geht doch einwandfrei.


----------



## SlaterB (4. Aug 2006)

Nova hat gesagt.:
			
		

> Sowas hab ich auch schon versucht, aber durch anlegen von Variablen mit gleichem Namen überschreibe ich ja nicht die Variablen in der Superklasse, sondern überdecke die nur.
> Java verwendet als Objekt "MediaSize" und sieht und verwendet daher die "original" Variablen und Methoden und nicht meine, oder hab ich da einen Denkfehler?


Mit Variablen überdecken kenne ich mich nicht ganz so gut aus, aber wenn Java auf diese zugreift, dann kannst du das doch auch? 
Dann definiere keine neuen, sondern benutze diese, setze sie im Konstruktor auf die benötigten Werte.

Ein Problem könnte da die Sichtbarkeit sein.. (z.B. nur Zugriff von package java.drucker erlaubt).


----------



## Mario_H (4. Aug 2006)

Bei Variablen haste Recht. Da nimmt's die alten.
Aber (hab die Klasse jetzt nicht vor mir) wer ließt Variablen direkt aus? Das geht doch meist über Methoden, welche du, wie in meinem Beispiel, probemlos überschreiben kannst, auch wenn dein Objekt als MediaSize-Objekt behandelt.


----------



## Nova (4. Aug 2006)

Das Problem ist das JAVA DIREKT "MediaSize.blabla" aufruft um die Papiergröße zu bekommen. Ich habe keinen einfluss auf diesen Aufruf.
Wenn ich nun von MediaSize erbe hat das keinen auf die original MediaSize, und Java ruft ja die original MediaSize auf.

Ist genauso wie wenn man eine Klasse schreibt die z.B. von JFrame erbt (nennen wir sie mal MyJFrame). Wenn man nun new JFrame() schreibt erstellt man eine Instanz von JFrame und nicht von MyJFrame, auch die Methodenaufrufe werden aus der JFrame Klasse genommen und nicht aus MyJFrame.
Wenn man die Variablen und Methoden aus der MyJFrame-Klasse haben muss man new MyJFrame() schreiben, in meinem Fall ist der Aufruf aber irgendwo in Java verbogen (in einer plattformabhängigen Klasse von der ich auch keinen Quelltext habe).

Die original Variablen kann ich auch nicht verändern da diese private sind, also nur DIREKT aus der MediaSize Klasse manipuliert werden können und nicht aus der Klasse die von MediaSize erbt.


----------



## Leroy42 (4. Aug 2006)

Ich verstehe eure Diskussion nicht.

Was ihr schreibt habe ich doch schon gestern(vorgestern?) geschrieben
und einfach _eigene Klassen_ genannt. Wenn die abzuleitende Klasse
also von irgendeiner nicht-eigenen (selbst geschriebenen) Klasse instantiiert
wird, geht das Ganze eben nicht.


----------



## SlaterB (4. Aug 2006)

mein Teil der Diskussion ging um den interessanten Umgang mit einem super-Konstruktor, der eine Exception wirft,
was zur Folge hat, dass die gesamte Superklasse nicht zu gebrauchen ist und daher komplett überschrieben werden muss,

natürlich ist das ganze in dieser Situation nicht hilfreich, wenn es keine 'benutzeMeinObjekt(objekt)'-Operation gibt, das war ja von Anfang an klar
(ob es so ist oder nicht weiß ich natürlich nicht, anscheinend ja  )


----------



## Nova (12. Aug 2006)

Ich habs jetzt erstmal so gelöst das ich ein eigenes JRE mitliefere in dem ich die MediaSize-Klasse durch meine ersetzt habe. Zum Aufrufen verwende ich eine Batch-Datei mit folgendem Inhalt:
START jre\bin\javaw -cp jre\lib;jre\lib\ext -jar MeinProgramm.jar

Funktioniert auch wunderbar und hat den Vorteil das ich immer das aktuelle JRE mitliefern kann, allerdings sinds auch 70MB extra (das Programm selbst hat nur 1,2MB).

Hab mir auch schon überlegt ob ich mit dem Classpath nicht was tricksen kann das ich nur die neue MediaSize.class mitlieferen und den Classpath so angebe das er meine MediaSize.class nimmt, aber den Rest aus dem installierten JRE, muss ich demnächst mal etwas rumprobieren...



mfg
Christian


----------



## Wildcard (12. Aug 2006)

Ich denke nicht das die SUN Lizenz dir gestatted die JRE manipuliert auszuliefern  :noe: 
Wende dich mal ans SUN Forum, oder schreib an Bug.


----------



## Leroy42 (12. Aug 2006)

Wildcard hat gesagt.:
			
		

> Ich denke nicht das die SUN Lizenz dir gestatted die JRE *manipuliert* auszuliefern  :noe:
> Wende dich mal ans SUN Forum, oder schreib an Bug.



Ist _manipuliert_ als Einschränkung des Verbots zu verstehen?

Bitte kurze Antwort aber keinen Link auf den Text der Lizenzbestimmung.

Es reicht mir bereits, tagtäglich _chineserisiertes_ Englisch zu entschlüsseln.


----------



## Wildcard (12. Aug 2006)

Manipuliert heißt verändert, und eine SUN-Klasse gegen eine eigene einzutauschen IST eine Veränderung


			
				jre1.5.0_06 readme.txt hat gesagt.:
			
		

> =======================================================================
> Redistribution of the J2SE Runtime Environment
> =======================================================================
> ....
> ...


Deutlicher kann man's glaub ich kaum sagen

EDIT btw: Es ist IMO auch nicht erlaubt SUN Quelltext zu kopieren und in eigene Klassen einzubauen.


----------



## Leroy42 (14. Aug 2006)

Wildcard hat gesagt.:
			
		

> *Manipuliert *heißt verändert, und eine SUN-Klasse gegen eine eigene einzutauschen IST eine Veränderung
> 
> 
> 
> ...



Ich weiß was manipuliert heißt; meine Frage zielte darauf ob es *nur verboten* ist,
ein *manipuliertes* JRE auszuliefern. Und genau das zeigt dein Zitat ja deutlich!

Danke!  :toll:


----------



## Wildcard (14. Aug 2006)

Ach so, jetzt verstehe ich die Frage   
Aber aufpassen, denn wie der Lizenz-Text auch sagt, ist es nicht erlaubt die JRE alleine auszuliefern (also ohne eigenes Programm).


----------



## Leroy42 (14. Aug 2006)

> (also ohne eigenes Programm)




```
public class MeinMain {
    static {
        System.out.println("Dies ist KEIN Hello World Programm!");
        System.exit(42*0);
    }
}
```

Reicht das?


----------



## Wildcard (14. Aug 2006)

Ich würde sagen das ist Ermessenssache:


			
				Readme hat gesagt.:
			
		

> (b) your Programs add significant and primary functionality to the
> Software,


----------

