Sunday, December 4, 2011

Motivation for java Generics + C++ template

 
 
http://en.wikipedia.org/wiki/Generics_in_Java 

Motivation for generics

The following block of Java code illustrates a problem that exists when not using generics. First, it declares an ArrayList of type Object. Then, it adds a String to the ArrayList. Finally, it attempts to retrieve the added String and cast it to an Integer.

List v = new ArrayList();
  v.add("test");
  Integer i = (Integer)v.get(0);        // Run time error

Although the code compiles without error, it throws a runtime exception (java.lang.ClassCastException) when executing the third line of code. This type of problem can be avoided by using generics and is the primary motivation for using generics.
Using generics, the above code fragment can be rewritten as follows:
 
List<String> v = new ArrayList<String>();
  v.add("test");
  Integer i = v.get(0); // (type error)  Compile time error
 
 
 http://stackoverflow.com/questions/36347/what-are-the-differences-between-generic-types-in-c-and-java
 
1.  
There is a big difference between them. In C++ you don't have to specify a class or an interface for the generic type. That's why you can create truly generic functions and classes, with the caveat of a looser typing.

<typename T> T sum(T a, T b) { return a + b; }

The method above adds two objects of the same type, and can be used for any type T that has the "+" operator available.

In Java you have to specify a type if you want to call methods on the objects passed, something like:

<T extends Something> T sum(T a, T b) { return a.add ( b ); }

In C++ generic functions/classes can only be defined in headers, since the compiler generates different functions for different types (that it's invoked with). So the compilation is slower. In Java the compilation doesn't have a major penalty, but Java uses a technique called "erasure" where the generic type is erased at runtime, so at runtime Java is actually calling ...

Something sum(Something a, Something b) { return a.add ( b ); }
 
... 
 
2.  
Basically in C++ templates are basically a glorified preprocessor/macro set (Note:
 since some people seem unable to comprehend an analogy, I'm not saying 
template processing is a macro).  In Java they are basically syntactic 
sugar to minimize boilerplate casting of Objects. 
 
... 
 
3. 
C++ templates have a number of features that Java Generics don't:
  • Use of primitive type arguments.
For example:
template<class T, int i>
class Matrix {
 
int T[i][i];
 
...
}
  • Use of default type arguments, which is one feature I miss in Java but there are backwards compatibility reasons for this;
  • C++ allows the use of primitive type arguments, Java doesn't; and
  • Java allows bounding of arguments.
For example:
public class ObservableList<T extends List> {
 
...
}


4. 


There is a great explanation of this topic in Java Generics and Collections By Maurice Naftalin, Philip Wadler. I highly recommend this book. To quote:
Generics in Java resemble templates in C++. ... The syntax is deliberately similar and the semantics are deliberately different. ... Semantically, Java generics are defined by erasure, where as C++ templates are defined by expansion.
 http://books.google.com.au/books?id=3keGb40PWJsC&dq=java+generics+and+collections&printsec=frontcover&source=bn&hl=en&sa=X&oi=book_result&ct=result&redir_esc=y#v=onepage&q&f=false


Thursday, December 1, 2011

Design by Contract + Precondition Weakened Example

Design by Contract

(Fowler UML Distilled, 3rd Ed)

Design by Contract uses three particular kinds of assertions: post-conditions, pre-conditions, and invariants. Pre-conditions and post-conditions apply to operations.

A post-condition is a statement of what the world should look like after execution of an operation.
For instance, if we define the operation "square root" on a number, the post-condition would take the form input = result * result, where result is the output and input is the input value.

A pre-condition is a statement of how we expect the world to be before we execute an operation. We might define a pre-condition for the "square root" operation of input > = 0. Such a pre-condition says that it is an error to invoke "square root" on a negative number and that the consequences of doing so are undefined.

An invariant is an assertion about a class.
In essence, this means that the invariant is added to pre-conditions and post-conditions associated with all public operations of the given class.
The invariant may become false during execution of a method, but it should be restored to true by the time any other object can do anything to the receiver.

The invariants and post-conditions of a class must apply to all subclasses. The subclasses can choose to strengthen these assertions but cannot weaken them. The pre-condition, on the other hand, cannot be strengthened but may be weakened.

http://www.stanford.edu/~pgbovine/programming-with-rep-invariants.htm

class Child {

  ...

  private void checkRep() {
    assert (0 <= age < 18);
    assert (birthdate + age == todays_date);
    assert (isLegalSSN(social_security_number));
  }
}

    ... and call checkRep() at the beginning and end of every public method
        The principle here is that clients should only be able to access your object via public methods, so ...
            at the beginning of a method, check to make sure the representation is intact before it starts operating on its internal state (fields)
            at the end of a method, check to make sure the representation is intact before it hands over control back to the client (caller)
        For example, look at the changeSSN() method:

class Child {
  ...

  public void changeSSN(int newSSN) {
    checkRep();
    ... method body ...
    checkRep();
  }


http://earthli.com/news/view_article.php?id=2183

An example for "The pre-condition of the parent class cannot be strengthened but may be weakened by the subclasses."

In general, the sub class may say that 'I don't mind if some requirment by the method from my parent class is not met, I will handle it (differently) in my method'.

- Example: a failback machansim

class Transmitter
{
  public Server Server { get; }

  [Pure]
  public virtual bool ServerIsReachable
  {
    get { return Server.IsReachable; }
  }

  public virtual void SendData(Data data)
  {
     Contracts.Requires(data != null);
     Contracts.Requires(ServerIsReachable);
     Contracts.Ensures(data.State == DataState.Sent);

     Server.Send(data);
  }

  [ContractInvariantMethod]
  protected void ObjectInvariant
  {
    Contract.Invariant(Server != null);
  }
}

class TransmitterWithFallback : Transmitter
{
  public Server FallbackServer { get; }

  [Pure]
  public override bool ServerIsReachable
  {
    get { return Server.IsReachable || FallbackServer.IsReachable; }
  }

  public override void SendData(Data data)
  {
    if (Server.IsReachable)
    {
      base.SendData(data);
    }
    else
    {
      FallbackServer.Send(data);
    }
  }

  [ContractInvariantMethod]
  protected void ObjectInvariant
  {
    Contract.Invariant(FallbackServer != null);
  }
}

Wednesday, November 16, 2011

Tuesday, November 1, 2011

static nested class and non-static nested (inner) class

http://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class

-----------------------------------static nested---------------------------------------

package pizza;
public class Rhino {

    ...

    public static class Goat {
        ...
    }
}
 
### 

Rhino.Goat goat = new Rhino.Goat(); 
 
###
NOTE: 
A non-static nested class (or 'inner class') has full access to the members of the class within which it is nested.
    
-----------------------------------non-static nested (inner)---------------------------------------

package pizza;
public class Rhino {

    public class Goat {
        ...
    }

    private void jerry() {
        Goat g = new Goat();
    }
}
 
### 
Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();
 
###
A static nested class does not have a reference to a nesting instance, so a static nested class cannot invoke non-static methods or access non-static fields of an instance of the class within which it is nested. 

http://stackoverflow.com/questions/1353309/java-static-vs-non-static-inner-class

http://www.brpreiss.com/books/opus5/html/page601.html

Friday, October 21, 2011

Declaring Constructors, Methods, and Variables in an enum

NOTE: the order of the line of the code is important for the following:

public enum SORT_ORDER
{
  ACCESSED_ASCENDING("accessed_ascending"),   
  ACCESSED_DESCENDING("accessed_descending");
   
  private SORT_ORDER(String p_value)
  {
   this.m_value = p_value;
  }

  private final String m_value;

  @Override
  public String toString()
  {
    return m_value;
  }
}

Wednesday, October 12, 2011

Linux: java.io.IOException: Too many open files

http://lj4newbies.blogspot.com/2007/04/too-many-open-files.html
http://www.karakas-online.de/forum/viewtopic.php?t=9834

1. check max file descriptor

cat /proc/sys/fs/file-max

change to higher if needed

2. add to
/etc/security/limits.conf

something like

* soft nofile 65535
* hard nofile 65535
 
3. log out and log back in  

Thursday, September 22, 2011

Singleton, Thread Safety, Volatile, Synchronized

On the singleton 'getter', add 'synchronized' for thread safety

otherwise, findbugs will say something like "Incorrect lazy initialization of static field ..."

More explanation:

http://www.ibm.com/developerworks/java/library/j-dcl/index.html

http://en.wikipedia.org/wiki/Singleton_pattern

Private Constructor

http://www.javapractices.com/topic/TopicAction.do?Id=40

If the programmer does not provide a constructor for a class, then the system will always provide a default, public no-argument constructor. To disable this default constructor, simply add a private no-argument constructor to the class. This private constructor may be empty.

In these cases, the lack of an accessbile constructor says to the caller : "There are no use cases for this class where you need to build an object. You can only use static items. I am preventing you from even trying to build an object of this class."

Friday, September 16, 2011

64bit Ubuntu won't run java

As of  Ubuntu 10.04 LT - the Lucid Lynx

you can't run a 32 bit jre on it, will tell you something like

exec: 1: ../../../bin/java: not found

In fact, 32 bit eclipse won't work either, and imaginable many other 32bit applications

Tuesday, August 23, 2011

Exception handling

- "Effetive Java" item 58: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors

- http://marxsoftware.blogspot.com/2010/04/i-recently-wrote-that-chapter-in.html


Thursday, August 11, 2011

BufferredReader


The Reader.ready() and InputStream.available() rarely work as you might like, and I don't suggest you use them. To read a file you should use
String line;
while ((line = reader.readLine()) != null)
    System.out.println("<"+line+">");



http://stackoverflow.com/questions/5244839/dose-bufferedreader-ready-method-ensure-that-readline-method-does-not-return


BufferedReader reader=null;
    try {
        reader = new BufferedReader(new StringReader("ABCD"));

        while (reader.ready()) {
            final String line = reader.readLine();
            System.out.println("<"+line+">");
        } catch (..)
    {
        ...
    }


So a BufferedReader is considered ready simply if the underlying stream is also ready. Since BufferedReader is a wrapper, this underlying stream could be any Reader implementation; hence the semantics of ready() are those declared on the interface:
Returns true if the next read() is guaranteed not to block for input, false otherwise. Note that returning false does not guarantee that the next read will block.
So you only really get timing guarantees, i.e. that read() will not block. The result of calling ready() tells you absolutely nothing about the content you'll get back from a read() call, and so cannot be used to elide a null check.

Tuesday, August 2, 2011

file name to java.io.File

String filePath = "com/?/work?/rest/resource/" + fileName; 

java.net.URL fileUrl = getClass().getClassLoader().getResource(filePath);

java.io.File rawFileData = new File (filUrl.toURI()); 

Thursday, July 28, 2011

after using dojo.mixin(), need to do some post op to get rid of all 'undefined' values that passed into constructor

 after using dojo.mixin(this, p_args); have to make sure that neither of the defined as member variable is 'undefined' and note that 'undefined' can be pass into the constructor (which is different from where the parameter is not given at all) will override that '' default value.

other wise will get something like

"error: Error: *.widget.SummaryRow
template: library"

so need to do some post op to get rid of all 'undefined' values.
------------------------------------------------------------

dojo.provide("*.widget.SummaryRow");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare("*.widget.SummaryRow", [ dijit._Widget,
        dijit._Templated ], {

    // Path to the template
    templateString : dojo.cache("*.widget",
            "templates/SummaryRow.html"),

    widgetsInTemplate : false,
   
    checkboxtitle : null,
    image : '',
    title : '',
    author : '',
    workflowstatus : '',
    description : '',
    contextpath : '',
    library : '',
    links : '',

    constructor : function(p_args) {
        dojo.mixin(this, p_args);
    },


    postMixInProperties : function() {
          alert("in postMixInProperties");
        this.library = this.getLibraryUuid(this.links);                     
    },

    getLibraryUuid : function(p_links) {
        alert("in getLibraryUuid(): p_links: " + p_links);
        return "WebContent";
    },

    postCreate : function() {
       
      this.inherited(arguments);
    }
});

Monday, July 25, 2011

Handle Parameters Override for RESTful service

1. Allow the user of the RESTful Service to be able to specify parameter that overrides attributes in the header is good practice since it is not always convenient for the user writing the client application to specify the attributes in the request header

2. For example, dojox.rpc.REST(<url>, <isJson>), a nice functionality, but you can't really explicitly specify what the 'Content-type' is except for whether it is application/json or not. But if the corresponding RESTful service handles parameter override, then the user can conveniently just put that into the <url>.

3. Arguably this deviate from the how REST should be different RPC, but practically, who cares?

opacity, z-index,

in Style

opacity: transparency, 0 is lowest, 1 is highest - in FF; IE is 0-100

z-index: layering, the higher the more on top the layer.

VBA: extract number from strings

http://www.ozgrid.com/VBA/ExtractNum.htm

Sunday, July 17, 2011

To pass string value as argument to a javascript function in HTML

To pass string value as argument to a javascript function in HTML

<li role="menuitem" id="createListItem">
                            <a tabindex="-1" href='javascript:onLeftMenuSelect("createListItem")'
                                id='createListItemLink'>Creates</a>
                        </li>

Thursday, July 14, 2011

Automated Testing: deletion before creation v.s. finally block (teardown, etc)

Deletion (if exist) before creation is the in general more recommended:

1.  Assuming that the Deletion logic is valid, the test cases should be guaranteed to rerun properly, even in case such as the Test run thread is forced to stop (JUnit stop button in Eclipse, anyone has not ever pressed?)


2. In some case, it is good to leave the data created/updated in the data store to assist test failure investigation.

Wednesday, July 13, 2011

using EARExpander

 http://publib.boulder.ibm.com/infocenter/wasinfo/v6r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/rxml_earexpander.html

e.g.

/opt/WebSphere/AppServer/bin/EARExpander.sh -ear /opt/sampleUI.ear -operationDir /opt/WebSphere/wp_profile/installedApps/eli80/PA_wcm.portlet.design.ear/ -operation collapse

Writer, OutputStream, InputStream

http://ostermiller.org/convert_java_outputstream_inputstream.html

Sunday, July 10, 2011

clear case commandline force cancel delivery

windows --> run --> cmd

V:\

cleartool startview jjwang_WCM_REST_80_int
cd  jjwang_WCM_REST_80_int
cleartool deliver -status
cleartool deliver -cancel

Thursday, July 7, 2011

Set environmental variable in Ubuntu

https://help.ubuntu.com/community/EnvironmentVariables

Persistent environment variables

So far we've only discussed ways set an environment variable value temporarily until the shell session in which it was set is closed. One may wonder if there is a way to somehow permanently set an environment variable to a certain value.
Note: The shell config files mentioned below are only meant to be read by particular shells and desktop environments and should not be used.

Session-wide environment variables

The below are not recommended but the previous solution (?) provided on this page did not work with the 10.04 desktop release. .pam_environment is not naturally procesed with the distribution.
Not recommended:
  • ~/.profile - This is probably the best file for placing environment variable assignments in, since it gets executed automatically by the DisplayManager during the startup process desktop session as well as by the login shell when one logs-in from the textual console.
  • ~/.bash_profile or ~./bash_login - If one of these file exist, bash executes it rather then "~/.profile" when it is started as a login shell. (Bash will prefer "~/.bash_profile" to "~/.bash_login"). However, these files won't influence a graphical session by default.
  • ~/.bashrc - Because of the way Ubuntu currently sets up the various script files by default, this may be the easiest place to set variables in. The default configuration nearly guarantees that this file will be executed in each and every invocation of bash as well as while logging in to the graphical environment. However, performance-wise this may not be the best thing to do since it will cause values to be unnecessarily set many times.

System-wide environment variables

Environment variable settings that affect the system as a whole (rather then just a particular user) should not be placed in any of the many system-level scripts that get executed when the system or the desktop session are loaded, but into
  • /etc/environment - This file is specifically meant for system-wide environment variable settings. It is not a script file, but rather consists of assignment expressions, one per line. Specifically, this file stores the system-wide locale and path settings.
Not recommended:
  • /etc/profile - This file gets executed whenever a bash login shell is entered (e.g. when logging in from the console or over ssh), as well as by the DisplayManager when the desktop session loads. This is probably the file you will get referred to when asking veteran UNIX system administrators about environment variables. In Ubuntu, however, this file does little more then invoke the /etc/bash.bashrc file.
  • /etc/bash.bashrc - This is the system-wide version of the ~/.bashrc file. Ubuntu is configured by default to execute this file whenever a user enters a shell or the desktop environment.
Note: When dealing with end-user/home desktop systems may be appropriate to place settings in the user's ~/.pam_environment files discussed above rather then the system-wide ones, since those files do not require one to utilize root privileges in order to edit and are easily moved between systems.

Monday, July 4, 2011

JavaScript: method undefined - add 'this.'

read about the scoping of javascript

javascript: 'has no method ...' - check the spelling

Object wcmrest:05966917-7cf0-4324-ac1a-31cac57cd817 has no method 'indexof'

in fact it should be 
indexOf, 
simple as that. 
JavaScript is 'type-less' after all.

Friday, July 1, 2011

Be careful with form 'onSubmit' method, may cause thread 'race' situation

<form onSubmit="send();return false;">
...
<button onclick='send()'>submit</button>
</form>


where the 'send()' method is a ajax call to certain service, this will result two thread trying to use the service at almost exact same time, hence the the 'race'

use x11vnc to connect to the 'real' display

using

vncserver :#
vncserver -kill :#

will only start sessions that is not the 'same' desktop

If you would like to remote into a machine with vnc and actually see and interact with the root desktop you can use x11vnc,

just
x11vnc

Wednesday, June 22, 2011

ubuntu unexpected operator for shell script

[ : unexpected operator

Ubuntu is strict on shell syntax

check if you can fix it by changing

#!/bin/sh => #!/bin/bash

Thursday, June 9, 2011

SVNServer set up on CentOS

courtesy of
http://wiki.centos.org/HowTos/Subversion
http://lincgeek.org/blog/?p=347

1.

[root@lucifer ~]yum install mod_dav_svn subversion

2.
[root@lucifer ~]vim /etc/httpd/conf/httpd.conf

change Server Name as its IP (not sure if it is necessary)

3.
[root@lucifer ~]service httpd start

[root@lucifer ~]chkconfig httpd on

4.
[root@lucifer ~]vim /etc/httpd/conf.d/subversion.conf

make it look like the following

# Make sure you uncomment the following if they are commented out
LoadModule dav_svn_module     modules/mod_dav_svn.so
LoadModule authz_svn_module   modules/mod_authz_svn.so

# Add the following to allow a basic authentication and point Apache to where the actual
# repository resides.
<Location /repos>
        DAV svn
        SVNPath /var/www/svn/repos
        AuthType Basic
        AuthName "Subversion repos"
        AuthUserFile /etc/svn-auth-conf
        Require valid-user
</Location>

NOTE: if you

see 403 "Forbidden You don't have permission to access  ...." 


check if you are using SVNParentPath instead of SVNPath

5.
Add the 1st User
[root@lucifer ~] htpasswd -cm /etc/svn-auth-conf yourusername
New password:
Re-type new password:
Adding password for user yourusername

Add additional user
[root@lucifer ~] htpasswd -m /etc/svn-auth-conf anotherusername
New password:
Re-type new password:
Adding password for user anotherusername

6.
Create the repo
[root@lucifer ~] cd /var/www/ -- Or wherever you placed your path above
[root@lucifer ~] mkdir svn
[root@lucifer ~] cd svn
[root@lucifer ~] svnadmin create repos
[root@lucifer ~] chown -R apache.apache /var/www/svn/*
[root@lucifer ~] chmod 770 -R /var/www/svn/*
[root@lucifer ~] service httpd restart

7.
Test it out
http://[yourmachine]/repos

8.
Add items to the repos with comments
[root@lucifer ~] svn import /tmp/mytestproj/ file:///var/www/svn/repos/mytestproj -m "Initial repository layout for mytestproj"
Adding         /tmp/mytestproj/main
Adding         /tmp/mytestproj/main/mainfile1.cfg
Adding         /tmp/mytestproj/configurations
Adding         /tmp/mytestproj/configurations/testconf1.cfg
Adding         /tmp/mytestproj/options
Adding         /tmp/mytestproj/options/testopts1.cfg

9.
Edit and Commit

[me@mylappy ~] cd mytestproj
[me@mylappy ~] vim configurations/testconf1.cfg -- Add or delete something and save.
[me@mylappy ~] svn commit -m "Added a line to testconf1.cfg."
Sending        configurations/testconf1.cfg
Transmitting file data .
Committed revision 2.

10.
Add to existing folder in the repo

Now this is all fine and dandy, but how do you add more files to an already existing repo directory? Easy, with the add argument. Go ahead and checkout your latest and greatest, copy a file over to a directory, add, then commit the changes.

11.
[me@mylappy ~] svn co http://yoursvnserver/repos/mytestproj
A    mytestproj/main
A    mytestproj/main/mainfile1.cfg
A    mytestproj/configurations
A    mytestproj/configurations/testconf1.cfg
A    mytestproj/options
A    mytestproj/options/testopts1.cfg
Checked out revision 2.

[me@mylappy ~] cd mytestproj
[me@mylappy ~] cp /etc/yum.repos.d/CentOS-Base.repo configurations/
[me@mylappy ~] svn add configurations/CentOS-Base.repo
A         configurations/CentOS-Base.repo

[me@mylappy ~] svn commit -m "Added the CentOS Yum repo file."
Adding         configurations/CentOS-Base.repo
Transmitting file data .
Committed revision 3.

Delete

[me@mylappy ~] svn delete configurations/CentOS-Base.repo
[me@mylappy ~] svn commit -m "Delete the CentOS Yum repo file."

Subclipse - get started

1. Windows->Open Perspectives->Other->SVN Explorer; Once the view is open, right click "New Location" and put in the URL pointing to your repo

2. to import the project to eclipse the 1st time, right click on the project and 'check out', follow the wizard to import it into the current workspace

3. the project should appear in your workspace then and you can immediately 'commit' the project if you don't want to keep it checked out

4. edit the files anyway you want, when save, the file/project will have a "*" next to its icon, meaning it's changed and different from the copy on the server.

5. to 'check in' the changes. right click on the file and 'Commit' with an comment for the change.

6. To add a local project to SVN repo, right click on that project -> Team ->Share Project->SVN ...

Note: as far as I see now, you can not add a project (and its files) that is under some other source control (e.g. clear case) to SVN

Set up Subclipse in Ubuntu

1. (install plugin)
http://subclipse.tigris.org/servlets/ProjectProcess?pageID=p4wYuA
2. (install the additional javaHL libraries)
$ apt-get install libsvn-java

3.  (get eclipse to pick these libraries)
add to eclipse.ini, under -vmargs


-Djava.library.path=/usr/lib/jni

Saturday, June 4, 2011

ItemFileWriteStore: newItem() was not passed an identity for the new item

bug Trac:
http://bugs.dojotoolkit.org/ticket/6562

ItemFileWriteStore.js source code:
http://bugs.dojotoolkit.org/browser/branches/1.0/dojo/trunk/data/ItemFileWriteStore.js?rev=12277

Friday, June 3, 2011

Query URL transformation

From "Matering Dojo" p275

But different server-side programs
require different forms of URLs.

For example:
mystore.php?query=A%&page=1&itemsperpage=10&sort=name

Rather than be dictatorial, QueryReadStore allows you to plug in code to
rewrite the dojo.data request as a URL. You do this by writing a subclass
of QueryReadStore and using that for your driver instead.


dojo.provide("dojobook.data.datasources.sample_rewriter" );

dojo.require("dojox.data.QueryReadStore" );

dojo.declare(
"dojobook.data.datasources.sample_rewriter" ,
dojox.data.QueryReadStore, {

fetch:function(request) {
request.serverQuery = {
q: request.query.substance.replace("*" , "%" ),
itemsperpage: request.count,
page: Math.floor(request.start / 10)
};

// Call superclasses' fetch
return this.inherited(arguments);
}
});

QueryReadStore sends both the request.query and the request.serverQuery
properties combined. In the previous example, mystore.php?q=A&page=10&
itemsperpage=10&query=A*&start=1&count=10 gets sent. As long as the extra
parameters do not interfere with the server program, you needn’t worry
about it. If they do, you can simply null out request.query.field in the
QueryReadStore subclass

Thursday, June 2, 2011

javascript dojo.body() undefined

Possibly some code directly under

<script/> tag. Try put them into a function and  call it on page load if necessary

Monday, May 30, 2011

referenced from:


className String|null
The optional name of the Class to declare.
The className will be used as a global name for a created constructor.
If you don't specify it, the class is assumed to be anonymous (new since V1.4).
If you specify it, the name will be stored in the property "declaredClass" in the created prototype.
superclass null|Object|Object[]
This parameter is either
  • null (no base class),
  • an object (a base class) or
  • an array of objects (multiple inheritance).
props Object
An object whose properties are copied (mixed in) to the created prototype after all other inheritance has been solved.
You can add an instance-initialization function by making it a property named "constructor".

Global:

Example: http://stackoverflow.com/questions/2444801/queryreadstore-loads-json-into-datagrid-but-jsonreststore-does-not-from-the-sam


dojo.declare("dojox.data.CustomStore", dojox.data.JsonRestStore, {
    _processResults: function(results, deferred){
        var items = SOME_MAPPING_FUNCTION_HERE(results);
        var count = COUNT_RESULTS_HERE;
        return {totalCount:deferred.fullLength || (deferred.request.count == count ? (deferred.request.start || 0) + count * 2 : count), items: items};
    }
}


To show how the inheritance chain works, we will create a new class derived from my.Thinger:
1
2
3
4
5
6
7
8
9
dojo.declare("my.OtherThinger", [my.Thinger], {
  divisor: 5,
  constructor: function(args){
    console.log('OtherThinger constructor called');
    this.total = this.count / this.divisor;
  }
});
var thing = new my.OtherThinger({ count:50 });
console.log(thing.total); // 10 

Local:


Now we have a 'base class', called my.Thinger.
If we don't want a globally accessible class we can easily make it local (since 1.4):
1
2
3
4
5
6
7
8
9
var localThinger = dojo.declare(null, {
  count: 100,
  constructor: function(args){
    dojo.mixin(this, args);
  }
});
var thing1 = new localThinger();
var thing2 = new localThinger({ count:200 });
console.log(thing1.count, thing2.count);