I'm working on making a programming language that compiles to JVM bytecode, and it highly relies on interfaces as types. I need some way to make an interface private, but have other code still be able to access it, but not make something that implements it.
I was thinking about using abstract classes with a private constructor, so only the classes in the same file would be able to access it. The only problem is that it is impossible to extend multiple abstract classes at once. For example, the structure of a simple compiled program would be this:
// -> Main.java
public class Main {
public static MyInteger getMyInteger() {
return new MyIntegerImpl(10);
}
public static void main(String[] args) {}
private interface MyInteger {
public int getValue();
}
private static class MyIntegerImpl implements MyInteger {
private final int value;
public int getValue() {
return value;
}
public MyIntegerImpl(int value) {
this.value = value;
}
}
}
And another file, in which there is a problem:
// -> OtherFile.java
public class OtherFile {
public static void main(String[] args) {
Main.MyInteger myInteger = Main.getMyInteger(); //Error: The type Main.MyInteger is not visible.
System.out.println(myInteger.getValue());
}
//I do not want this to be allowed
public static class sneakyInteger implements Main.MyInteger { //Error(Which is good)
public int getValue() {
System.out.println("Person accessed value");
return 10;
}
}
}
The reason why I want to do this is so one person can not mess up any other person's code by providing their own implementations of things that should be only implemented by that other person.
Any help would be much appreciated.
I'm pretty sure that you should think again about what you are trying to do and change approach, but the answer for your question is to add to the interface some empty void method that is getting the parameter of the inner private class specific for the wrapper class
public class Test {
private class InnerPrivateClass {
private InnerPrivateClass() {}
}
public interface MyInteger {
int getValue();
void accept(InnerPrivateClass c);
}
private class MyIntegerImpl implements MyInteger {
#Override
public int getValue() {
return 0;
}
#Override
public void accept(InnerPrivateClass c) {}
}
}
However, as I said, I don't like this and for me it means that your idea is broken
Related
I'm probably going about this in the most complicated way, but I'm hoping what I'm trying to do makes sense here.
Suppose I have some set of unrelated, generated classes and I want to Decorate them to create some kind of common API. So something like:
public abstract class GeneratedDecorator<T> {
private T generated;
public T getGenerated() { return generated; }
public void setGenerated(T generated) { this.generated = generated; }
public abstract String getString();
public static class ClassA extends GeneratedDecorator<GeneratedClassA> {
#Override
public String getString() { return getGenerated().getThisString(); }
}
public static class ClassB extends GeneratedDecorator<GeneratedClassB> {
#Override
public String getString() { return getGenerated().getADifferentString(); }
}
}
Now, to use this new fancy class I just say:
GeneratedDecorator.ClassA a = new GeneratedDecorator.ClassA();
a.setGenerated(myGeneratedInstanceA);
a.getString();
Ok so far so-so ... but now I want to manage an array of these Decorators.
So let's try:
public abstract class DecoratorBundle<T extends GeneratedDecorator> {
private static final int MAX_ROWS = 10;
private T[] bundle;
DecoratorBundle() { bundle = createBundle(); }
public String getString(int index) { return bundle[index].getString(); }
public void setRow(??? generated, int index ) {
//check index of bundle, if null create a new instance of appropriate type and set bundle[index] = new instance
//call setGenerated on instance at index
}
protected abstract T[] createBundle();
public static class ClassA extends DecoratorBundle<GeneratedDecorator.ClassA> {
#Override
protected GeneratedDecorator.ClassA[] createBundle() {
return new GeneratedDecorator.ClassA[MAX_ROWS];
}
}
public static class ClassB extends DecoratorBundle<GeneratedDecorator.ClassB> {
#Override
protected GeneratedDecorator.ClassB[] createBundle() {
return new GeneratedDecorator.ClassB[MAX_ROWS];
}
}
}
Here's where I'm stuck ... I want this DecoratorBundle to have a setRow(??? generated, int index) where the parameter is of the GeneratedDecorator's type (i.e, GeneratedClassA or GeneratedClassB). Seems like type erasure will probably make this impossible, but it would be really nice to have this DecoratorBundle class to completely manage it's bundle array. It currently is able to instantiate the array, but I want some way for it to create a new GeneratedDecorator-type and assign it in a setRow method.
If I'm going about this completely wrong then I would love to hear another idea.
there I'm pretty new to Java and have german class and method titles. This Code is meant to give a string output for every class extending "Musiker". I have already looked on SO but my problem is that changing it to static gives an error on the class itself. The main reason why I open a new Question is, that every other class is working as planned. And please don't wonder why the Strings look weird, the Book I copied this from is meant to be humoristic.
public class Proberaum {
public static void main(String[] args) {
try {
Musiker saenger = new Saenger();
Musiker gitarrist = new Gitarrist();
Musiker bassist = new Bassist();
Musiker trompeter = new Trompeter();
Musiker backgroundSaengerin = new BackgroundSaengerin();
machtMusik(saenger, gitarrist, bassist, trompeter, backgroundSaengerin);
} catch(Exception e) {
new Exception().printStackTrace();
}
}
public static void machtMusik(Musiker... gruppe) {
for(Musiker musiker : gruppe) {
musiker.musizieren();
}
}
public class Musiker {
private String name;
private int alter;
private Band band;
public void musizieren() {
System.out.println("OO Mmmmmmmmh, OO Mmmmmmmmh");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAlter() {
return alter;
}
public void setAlter(int alter) {
this.alter = alter;
}
public Band getBand() {
return band;
}
public void setBand(Band band) {
this.band = band;
}
}
public class Band {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Saenger extends Musiker {
#Override
public void musizieren() {
this.singen();
}
public void singen() {
System.out.println("Oh, bäbi, juuuu a mei sannnnscheiiiiin");
}
}
public class BackgroundSaengerin extends Saenger {
}
public class Bassist extends Musiker {
}
public class Gitarrist extends Musiker {
public void musizieren() {
System.out.println("Tschiiiiiingzäääängggggg");
}
}
public class Trompeter extends Musiker {
}
}
Your Saenger class is actually a non-static member of the Proberaum class. Because it's non-static, you actually need to create an instance of Proberaum before you can use any of these classes:
Proberaum proberaumObject = new Proberaum();
Musiker saenger = new proberaumObject.Saenger();
In your case, classes inside classes is probably not what you want to do. If you extract each of your classes into its own file, you should find your problem going away. (If that's not possible for whatever reason, declaring your subclasses as static should work too.)
Like Joe C also mentioned in his answer: the core of the problem is that your classes Saenger, Musiker, etc etc. are all nested classes (nested inside Proberaum), but they are defined as non-static.
In Java, non-static nested classes are called "inner classes". Inner classes have implicit access to their enclosing class members (even private ones), but of course the flipside of this is that there first needs to be an object of that enclosing class for the inner class to reference. That is why the compiler is complaining in your example: you're trying to create an object of class Saenger, which is an inner class of Proberaum, so to create that object it needs to have a reference to an object of type Proberaum. Since you're doing the object creation in the (static) main method, no such object exists.
So, to fix, you have to change your inner classes. Easiest is to declare them all static. Note that you can do this is in addition to be making them public:
public static class Seanger extends Musiker { ...
As also remarked elsewhere however, you really should not put every class in the same file. Learn to work with one class per file, it's the Java Way™.
Instead of declaring the nested classes as static, one can alternatively create objects of nested classes like mentioned below.
Proberaum proberaumObject = new Proberaum();
Musiker saenger = proberaumObject.new Saenger();
I am way over thinking this: What I am trying to do is [hopefully not reinvent the wheel and] come up w/ a [Android] Java eventing mechanism that allows subclasses to pre-define an arbitrary set of "features" with getters and setters that fire individual callbacks.
I think I am fusioning some combination of Command, Visitor, Decorator, Facade and Observer patterns here, and confusing myself along the way.
I have been programming for well over 20 years, but I feel like a n00b on this fairly simple problem! :(
I have searched SO for the compiler error and read many of the results, but I still haven't found a solution that works for me.
(How to make a Java class that implements one interface with two generic types? seems to be the most relevant one that I have found, but I also want to generically get the values and fire events to callbacks when they are set).
First, let the below mostly valid code speak for itself...
interface IFeature
{
}
interface IFeatureCallbacks<T extends IFeature>
{
boolean onChanged(Feature<T> c);
}
public static class Feature<T extends IFeature>
{
private Set<IFeatureCallbacks<T>> listeners = new LinkedHashSet<>();
public void addListener(IFeatureCallbacks<T> listener)
{
listeners.add(listener);
}
public void removeListener(IFeatureCallbacks<T> listener)
{
listeners.remove(listener);
}
protected void onChanged()
{
for (IFeatureCallbacks<T> listener : listeners)
{
listener.onChanged(this);
}
}
}
//
interface IFeatureA
extends IFeature
{
int getA();
}
interface IFeatureACallbacks
extends IFeatureCallbacks<IFeatureA>
{
}
public static class FeatureA
extends Feature<IFeatureA>
implements IFeatureA
{
private int a;
public void setA(int value)
{
a = value;
onChanged();
}
#Override
public int getA()
{
return a;
}
}
//
interface IFeatureB
extends IFeature
{
boolean getB();
}
interface IFeatureBCallbacks
extends IFeatureCallbacks<IFeatureB>
{
}
public static class FeatureB
extends Feature<IFeatureB>
implements IFeatureB
{
private boolean b;
public void setB(boolean value)
{
b = value;
onChanged();
}
#Override
public boolean getB()
{
return b;
}
}
//
interface IDeviceWithFeatureA
extends IFeatureA
{
}
interface IDeviceWithFeatureACallbacks
extends IFeatureACallbacks
{
}
public static class DeviceWithFeatureA
extends Feature<IDeviceWithFeatureA>
implements IDeviceWithFeatureA
{
FeatureA a = new FeatureA();
public void addListener(IDeviceWithFeatureACallbacks listener)
{
a.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
}
//
interface IDeviceWithFeatureB
extends IFeatureB
{
}
interface IDeviceWithFeatureBCallbacks
extends IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureB>
implements IDeviceWithFeatureB
{
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureBCallbacks listener)
{
b.addListener(listener);
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
The above code seems to work fine, albeit something about it smells a bit off.
The problem is when I try to do this:
interface IDeviceWithFeatureAAndFeatureB
extends IFeatureA, IFeatureB
{
}
/*
Compiler error:
'IFeatureCallbacks' cannot be inherited with different type arguments 'IFeatureA' and 'IFeatureB'
*/
interface IDeviceWithFeatureAAndFeatureBCallbacks
extends IFeatureACallbacks, IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureAAndFeatureB>
implements IDeviceWithFeatureAAndFeatureB
{
FeatureA a = new FeatureA();
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureAAndFeatureBCallbacks listener)
{
a.addListener(listener);
b.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
I am less interested in trying to figure out how to make what I am trying to do compilable, and I am more interested in what about my abuse of a pattern is way off base so that I can re-write it to be both simpler and compile.
You are abusing the basic "pattern" of OOP -- inheritance. The adage is that "favor composition over inheritance". Think in terms of "contains", instead of "is-a".
Take Zoo for example. A zoo is just a bunch of animals, right? So naturally, we may want to declare Zoo as subtype of Set<Animal>. Perhaps even have class Zoo extends HashSet<Animal>.
However, that is likely a wrong design. A zoo is actually a lot of things. It contains a set of animals, sure; but it also contains a set of people (as workers, not exhibits (although...) ). So it's better to
class Zoo
Set<Animal> animals(){ ... }
Set<Person> workers(){ ... }
Anywhere we need to treat a zoo as a set of animals, just use zoo.animals(); think of it as a type cast, or projection. We don't need inheritance here.
In your design, you have too many types; what's worse, too many type relationships. It seems that you simply need one generic class that reads/writes value of T, and contains listeners of T
class Feature<T>
T value;
// getter
// setter
Set<ChangeListener<T>> listeners;
interface ChangeListener<T>
void onChange(T oldValue, T newValue)
A device contains a bunch of features
class SomeDevice
Feature<Integer> featureA = new Feature<>();
Feature<Boolean> featureB = new Feature<>();
That's it. You can operate on feature A of the device by operating on itsfeatureA.
I would like to ask you some tips about this java scenario:
I have a simple interface called Sequence that performs some basic operation. Now I would like to implement some additional methods in a separate class, called SequenceWrapper, that implements the Sequence defined above. Here is some example code that looks like my real code:
public interface Sequence {
public void methodOne();
public int methodTwo();
}
public abstract class SequenceWrapper implements Sequence {
private wrappedSequence = null;
public SequenceWrapper(Sequence sequence){
this.wrappedSequence = sequence;
}
public void methodOne(){
wrappedSequence.methodOne();
}
public int methodTwo(){
return wrappedSequence.methodTwo();
}
}
public class ConcreteWrapper extends SequenceWrapper {
public ConcreteWrapper(Sequence sequence){
super(sequence);
}
// Just an example
public int addMethodOne(){
int a = super.methodTwo();
return a + 3;
}
}
Now if I want to implements a class with another method (say 'addMethodTwo()') I can simply extends the 'ConcreteWrapper' class and add only the new method:
public class ConcreteWrapperTwo extends ConcreteWrapper {
public ConcreteWrapperTwo(Sequence sequence){
super(sequence);
}
public int addMethodTwo(){
int a = super.methodTwo();
return a + 30;
}
}
What do you think? Is this code correct or it's preferable another strategy??
Thanks in advance
First, your private wrappedSequence = null; has no type.
I suppose you meant private Sequence wrappedSequence = null;
Second, in your example you will never be able to instantiate any of the classes, since all of them receive another Sequence in the constructor and there is no way of create the first instance of Sequence.
Third, composition over inheritance is a good approach, if you really need it. Usually you wrap an object when you need to hide or protect the access to the wrapped object. In your case, within the wrapper you are exposing all of the methods of the wrapped object. You then create new methods that will affect the wrapper object, but not the wrapped one.
What you probably need is just a normal inheritance scenario:
I would like to walk you through you a breakdown for this Java scenario:
I have a simple interface called Sequence that performs some basic operation. Now I would like to implement some additional methods in a separate class, called SequenceWrapper that implements the Sequence as defined above. Here is some example code to explain what I mean:
public interface Sequence {
public void methodOne();
public int methodTwo();
}
public abstract class AbstractSequence implements Sequence {
public SequenceWrapper( ){ }
public void methodOne(){
//basic behavior here
}
public int methodTwo(){
//basic behavior here
}
}
public class ConcreteSequence extends AbstractSequence {
public ConcreteSequence ( ){
super( );
}
// Just an example
public int addMethodOne(){
int a = methodTwo();
return a + 3;
}
}
public class ConcreteSequenceTwo extends AbstractSequence {
public ConcreteSequenceTwo( ){
super( );
}
public int addMethodTwo(){
int a = methodTwo();
return a + 30;
}
}
I have a class called ContentStream... the problem is that the inner class AddRectancle suppose to get the info of the getter of the class GraphicBeginn...I thought the class ContentStream can reach the getter at least as the getter is public ... plse tell me how to
public class ContentStreamExt extends ContentStreamProcessor
{
private Matrix graphicalMatrix;
public ContentStreamProcessorExt(ExtListener extListener)
{
super(extListener);
}
private void enhanceAdditional()
{
GraphicBeginn beginnGraphic = new GraphicBeginn();
super.register("a", beginnGraphic);
super.register("b", new AddRectangle(beginnGraphic));
}
private static class AddRectangle(GrapicBeginn beginn)
{
// should get the info of uUx and uUy
}
private static class GraphicBeginn implements ContentOperator
{
private float uUx;
private float uUy;
public float getuUx()
{
return this.uUx;
}
public float getuUy()
{
return this.uUy;
}
..... // the input for uUx and uuy will be created in a method
}
The code you gave has a number of problems, it doesn't compile correctly as another poster has noted. It also appears you are providing a method signature while also declaring a class called "AddRectange". Is this a class or a method? You need to decide which, it can't be both. Here is an example that I think illustrates what you're trying to do in a general sense:
public class SampleClass {
public SampleClass() {
}
private void sampleClassMethod() {
A a = new A();
a.acceptB(new B());
}
private class A {
public void acceptB(B bObject) {
System.out.println(bObject.memberVar1);
}
}
private class B {
private int memberVar1 = 5;
}
}
If i understand your question correctly, The add rectangle class should be passed an instance of graphic begin on which it can invoke the public getters. This wiring can be done by the content stream class.
By the way the following is syntactically invalid
private static class AddRectangle(GrapicBeginn beginn)