// Java class structs.S is a proxy for talking to a Go program.
//   gobind -lang=java structs
//
// File is generated by gobind. Do not edit.
package structs;

import go.Seq;

public final class S implements Seq.Proxy {
    static { Structs.touch(); }
    
    private final Seq.Ref ref;
    
    @Override public final int incRefnum() {
          int refnum = ref.refnum;
          Seq.incGoRef(refnum);
          return refnum;
    }
    
    S(int refnum) { this.ref = Seq.trackGoRef(refnum); }
    
    public S() { this.ref = Seq.trackGoRef(__New()); }
    
    private static native int __New();
    
    public final native double getX();
    public final native void setX(double v);
    
    public final native double getY();
    public final native void setY(double v);
    
    public native S identity() throws Exception;
    public native double sum();
    @Override public boolean equals(Object o) {
        if (o == null || !(o instanceof S)) {
            return false;
        }
        S that = (S)o;
        double thisX = getX();
        double thatX = that.getX();
        if (thisX != thatX) {
            return false;
        }
        double thisY = getY();
        double thatY = that.getY();
        if (thisY != thatY) {
            return false;
        }
        return true;
    }
    
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(new Object[] {getX(), getY()});
    }
    
    @Override public String toString() {
        StringBuilder b = new StringBuilder();
        b.append("S").append("{");
        b.append("X:").append(getX()).append(",");
        b.append("Y:").append(getY()).append(",");
        return b.append("}").toString();
    }
}

// Java class structs.S2 is a proxy for talking to a Go program.
//   gobind -lang=java structs
//
// File is generated by gobind. Do not edit.
package structs;

import go.Seq;

public final class S2 implements Seq.Proxy, I {
    static { Structs.touch(); }
    
    private final Seq.Ref ref;
    
    @Override public final int incRefnum() {
          int refnum = ref.refnum;
          Seq.incGoRef(refnum);
          return refnum;
    }
    
    S2(int refnum) { this.ref = Seq.trackGoRef(refnum); }
    
    public S2() { this.ref = Seq.trackGoRef(__New()); }
    
    private static native int __New();
    
    public native void m();
    public native String string();
    @Override public boolean equals(Object o) {
        if (o == null || !(o instanceof S2)) {
            return false;
        }
        S2 that = (S2)o;
        return true;
    }
    
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(new Object[] {});
    }
    
    @Override public String toString() {
        return string();
    }
}

// Java class structs.Structs_ is a proxy for talking to a Go program.
//   gobind -lang=java structs
//
// File is generated by gobind. Do not edit.
package structs;

import go.Seq;

public final class Structs_ implements Seq.Proxy, I {
    static { Structs.touch(); }
    
    private final Seq.Ref ref;
    
    @Override public final int incRefnum() {
          int refnum = ref.refnum;
          Seq.incGoRef(refnum);
          return refnum;
    }
    
    Structs_(int refnum) { this.ref = Seq.trackGoRef(refnum); }
    
    public Structs_() { this.ref = Seq.trackGoRef(__New()); }
    
    private static native int __New();
    
    public native void m();
    @Override public boolean equals(Object o) {
        if (o == null || !(o instanceof Structs_)) {
            return false;
        }
        Structs_ that = (Structs_)o;
        return true;
    }
    
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(new Object[] {});
    }
    
    @Override public String toString() {
        StringBuilder b = new StringBuilder();
        b.append("Structs_").append("{");
        return b.append("}").toString();
    }
}

// Java class structs.I is a proxy for talking to a Go program.
//   gobind -lang=java structs
//
// File is generated by gobind. Do not edit.
package structs;

import go.Seq;

public interface I {
    public void m();
    
}

// Java class structs.Structs is a proxy for talking to a Go program.
//   gobind -lang=java structs
//
// File is generated by gobind. Do not edit.
package structs;

import go.Seq;

public abstract class Structs {
    static {
        Seq.touch(); // for loading the native library
        _init();
    }
    
    private Structs() {} // uninstantiable
    
    // touch is called from other bound packages to initialize this package
    public static void touch() {}
    
    private static native void _init();
    
    private static final class proxyI implements Seq.Proxy, I {
        private final Seq.Ref ref;
        
        @Override public final int incRefnum() {
              int refnum = ref.refnum;
              Seq.incGoRef(refnum);
              return refnum;
        }
        
        proxyI(int refnum) { this.ref = Seq.trackGoRef(refnum); }
        
        public native void m();
    }
    
    
    public static native S identity(S s);
    public static native S identityWithError(S s) throws Exception;
}
