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

import go.Seq;

/**
 * A generic comment with &lt;HTML&gt;.
 */
public final class NoDoc implements Seq.Proxy {
    static { Doc.touch(); }
    
    private final Seq.Ref ref;
    
    @Override public final int incRefnum() {
          int refnum = ref.refnum;
          Seq.incGoRef(refnum);
          return refnum;
    }
    
    NoDoc(Seq.Ref ref) { this.ref = ref; }
    
    public NoDoc() { this.ref = __New(); }
    
    private static native Seq.Ref __New();
    
    @Override public boolean equals(Object o) {
        if (o == null || !(o instanceof NoDoc)) {
            return false;
        }
        NoDoc that = (NoDoc)o;
        return true;
    }
    
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(new Object[] {});
    }
    
    @Override public String toString() {
        StringBuilder b = new StringBuilder();
        b.append("NoDoc").append("{");
        return b.append("}").toString();
    }
}

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

import go.Seq;

/**
 * S is a struct.
 */
public final class S implements Seq.Proxy {
    static { Doc.touch(); }
    
    private final Seq.Ref ref;
    
    @Override public final int incRefnum() {
          int refnum = ref.refnum;
          Seq.incGoRef(refnum);
          return refnum;
    }
    
    /**
     * NewS is a constructor.
     */
    public S() {
        this.ref = __NewS();
    }
    
    private static native Seq.Ref __NewS();
    
    S(Seq.Ref ref) { this.ref = ref; }
    
    /**
     * SF is a field.
     */
    public final native String getSF();
    /**
     * SF is a field.
     */
    public final native void setSF(String v);
    
    /**
     * After is another method.
     */
    public native void after();
    /**
     * Before is a method.
     */
    public native void before();
    @Override public boolean equals(Object o) {
        if (o == null || !(o instanceof S)) {
            return false;
        }
        S that = (S)o;
        String thisSF = getSF();
        String thatSF = that.getSF();
        if (thisSF == null) {
            if (thatSF != null) {
                return false;
            }
        } else if (!thisSF.equals(thatSF)) {
            return false;
        }
        return true;
    }
    
    @Override public int hashCode() {
        return java.util.Arrays.hashCode(new Object[] {getSF()});
    }
    
    @Override public String toString() {
        StringBuilder b = new StringBuilder();
        b.append("S").append("{");
        b.append("SF:").append(getSF()).append(",");
        return b.append("}").toString();
    }
}

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

import go.Seq;

/**
 * S2 is a struct.
 */
public final class S2 implements Seq.Proxy {
    static { Doc.touch(); }
    
    private final Seq.Ref ref;
    
    @Override public final int incRefnum() {
          int refnum = ref.refnum;
          Seq.incGoRef(refnum);
          return refnum;
    }
    
    S2(Seq.Ref ref) { this.ref = ref; }
    
    public S2() { this.ref = __New(); }
    
    private static native Seq.Ref __New();
    
    @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() {
        StringBuilder b = new StringBuilder();
        b.append("S2").append("{");
        return b.append("}").toString();
    }
}

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

import go.Seq;

/**
 * I is an interface.
 */
public interface I {
    /**
     * IM is a method.
     */
    public void im();
    
}

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

import go.Seq;

public abstract class Doc {
    static {
        Seq.touch(); // for loading the native library
        _init();
    }
    
    private Doc() {} // 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(Seq.Ref ref) { this.ref = ref; }
        
        public native void im();
    }
    
    /**
     * C is a constant.
     */
    public static final boolean C = true;
    
    /**
     * A group of vars.
     */
    public static native void setNoDocVar(double v);
    /**
     * A group of vars.
     */
    public static native double getNoDocVar();
    
    /**
     * A specific var.
     */
    public static native void setSpecific(String v);
    /**
     * A specific var.
     */
    public static native String getSpecific();
    
    /**
     * V is a var.
     */
    public static native void setV(String v);
    /**
     * V is a var.
     */
    public static native String getV();
    
    public static native void f();
    public static native S newS();
}
