// Code generated by gobind. DO NOT EDIT.

// Java class structs.S is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java structs
package structs;

import go.Seq;

public final class S implements Seq.Proxy {
    static { Structs.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    S(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
    
    public S() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
    
    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();
    }
}

// Code generated by gobind. DO NOT EDIT.

// Java class structs.S2 is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java structs
package structs;

import go.Seq;

public final class S2 implements Seq.Proxy, I {
    static { Structs.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    S2(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
    
    public S2() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
    
    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();
    }
}

// Code generated by gobind. DO NOT EDIT.

// Java class structs.Structs_ is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java structs
package structs;

import go.Seq;

public final class Structs_ implements Seq.Proxy, I {
    static { Structs.touch(); }
    
    private final int refnum;
    
    @Override public final int incRefnum() {
          Seq.incGoRef(refnum, this);
          return refnum;
    }
    
    Structs_(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
    
    public Structs_() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
    
    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();
    }
}

// Code generated by gobind. DO NOT EDIT.

// Java class structs.I is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java structs
package structs;

import go.Seq;

public interface I {
    public void m();
    
}

// Code generated by gobind. DO NOT EDIT.

// Java class structs.Structs is a proxy for talking to a Go program.
//
//   autogenerated by gobind -lang=java structs
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 int refnum;
        
        @Override public final int incRefnum() {
              Seq.incGoRef(refnum, this);
              return refnum;
        }
        
        proxyI(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
        
        public native void m();
    }
    
    
    public static native S identity(S s);
    public static native S identityWithError(S s) throws Exception;
}
