Agent and Component implementations
From Indus Communities
Class declarations define new reference types and describe how they implement agents and components. Every class must implement either an Agent or Component or extend a class that implements an Agent or Component. A class that implements an agent is different from a class that implements a component. A class that implements a component describes its behavior, either by composing member components using connectors or by logic implemented in its methods, whereas a class that implements an agent makes use of connectors and channels to describe the behavior of a composite system where the agent composes components using connectors and communicates with other agents using channels.
A variable whose declared type is a Agent or Component type may have as its value as reference to any instance of a class which implements the specified Agent or Component.
Class Declaration:
ClassModifiers (opt) Class Identifier implements InterfaceName {
//Class Body
}
The Identifier in the above declaration is the name of the class. Each class must mandatorily implement an Agent or Component whose name must be specified in the class declaration.
A class declaration may include class modifiers. Class modifiers may be one of the following
- Public
- Protected
- Private
- Abstract
- Final
- Strictfp
If two or more class modifiers appear in a class declaration, then it is customary, though not required, that they appear in the order consistent with that shown above. It is a compile time error for a modifier to appear more than once in a class declaration.
An abstract class is a class that is incomplete. Only abstract classes may have abstract methods, methods that are declared but not yet implemented. If a class that is not abstract contains abstract methods, then a compile-time error occurs. A class C has abstract methods if any one of the following is true
- C explicitly contains a declaration of an abstract method
- Any of C’s super classes declares an abstract method that has not been implemented in C or any of its super classes
A class that inherits an abstract class must be declared as abstract whereas a class that implements an abstract class may not be declared abstract. A subclass of an abstract class that is not itself abstract may be instantiated, resulting in the execution of a constructor for the abstract class and therefore, the execution of the field initializers for instance variables of that class. It is a compile time error to instantiate an abstract class or declare abstract methods in such a way that it is impossible for a class to implement them together.
A class can be declared final if its definition is complete and no subclasses are desired or acquired. A compile-time error occurs if a class is declared both final and abstract or if the final class appears in an extends clause of a class inheriting behavior from another class.
Indus does not support the provision of inner classes and nested classes as it supports reuse only through a mix of single inheritance and method reuse (see below in section on Inheritance).
The optional extends clause in a class declaration specifies the direct super class of the current class. A class is said to be a direct subclass of the class it extends. Final classes are not allowed to have subclasses. The subclass relationship is the transitive closure of direct subclass relationship. A class A is a subclass of class C if either of the following is true:
- A is the direct subclass of C
- There exists a class B such that A is a subclass of B and B is a subclass of C, applying this definition recursively
Unlike in Java, the implements clause in a class declaration is not optional. In Indus, the implements clause in the class declaration lists the name of the agent or component that the class implements. Unless the class being declared is abstract, the declarations of all the member methods of the agent or component that the class implements must be implemented either by declaration in this class or by an existing method declaration inherited from the direct super class. A class in Indus can, at the most, implement one agent or component declaration. There is no concept of member interfaces in Indus classes unlike in Java. However, agent and component interfaces in Indus may have nested interfaces. In such cases, classes that implement interfaces that are nested within other interfaces may not be declared static. Such classes may not declare static members. Inner classes may not declare static members unless they are compile-time constant fields.
A class body may contain declarations of members of the class, i.e. fields and methods. A class body may also contain instance initializer, static intializer and declarations of constructors for the class. Classes and Interfaces can not be members of classes.
The members of a class type are all of the following :
- Members inherited from its direct super class, except in class object which has no direct super class.
- Members declared in the body of the class.
Members of a class that are declared private are not inherited by subclasses of that class. Only members of a class that are declared protected or public are inherited by subclasses. Constructors, static initializers, and instance initializers are not members and therefore, are not inherited. Even though a class might not be declared public, instances of the class might be available at run time if it has a public super class.
Variables of a class are introduced by field declarations.
FieldDeclarations: FieldModifiers (opt) Type VariableDeclarators VariableDeclarator: VariableDeclaratorID = VariableInitializer VariableInitializer: Expression ArrayInitializer VariableDeclaratorID: Identifier VariableDeclaratorID[ ]
It is a compile-time error for a body of a class declaration to declare two fields of the same name. Methods, types and fields may have the same name since they are using different contexts.
If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in the super classes. A class inherits from its direct super class all the non-private fields of the super class. A sub class may access a private field member in a super class but will not inherit it. Sub classes inherit all other fields from super classes.
Field modifiers are always one of the following
- Public
- Protected
- Private
- Static
- Final
- Transient
- Volatile
A compile-time error occurs if the same modifier appears more than once in a field declaration, or a field declaration has more than one of the access modifiers, public, protected and private. If two or more distinct field modifiers appear in a field declaration, it is customary, though not required, that they appear in the order consistent with that shown above.
If a field is declared static, there exists exactly only one instance of the field, no matter how many instances of the class may eventually be created. A static field is instantiated when the class is initialized. A field that is not declared static is called an instance variable which means that whenever a new instance of a class is created, a new variable associated with that instance is created for every instance variable declared in that class or any of its super classes.
A field can be declared final. Both static and non-static fields may be declared final. It is a compile-time error if a blank final static variable is not definitely assigned by a static intializer of the class in which it is declared. A blank final non-static variable must definitely be assigned at the end of every constructor of the class in which it is declared, saving which a compile-time error occurs.
Variables may be marked transient to indicate that they are not part of a persistent state of an object.
Like in Java, Indus allows threads that access shared variables to keep private working copies of the variables. This allows for an efficient implementation of shared variables. A field may be declared volatile in which case the thread must reconcile its working copy of the field with the master copy every time it is accesses the variable.
If a field declarator contains a variable initializer, then it has the semantics of an assignment to the declared variable . If the declarator is for a static field, then the variable initializer is evaluated and the assignment performed exactly once, when the class is initialized, else if the declarator is for a non-static field, then the variable initializer is evaluated and the assignment performed each time an instance of the class is created.
In the case of both static and non-static variables, a class that assigns a value to them, when the variables are actually declared in a direct or indirect super class, hides any previous assignment made to these variables in any of its super classes.
Initialization expressions for non-static variables are permitted to refer to the current object this and to use the keyword super. This is not true of static variables.
The declaration of a member variable always needs to appear before it is used.
A method declares an executable port that can be invoked, passing a fixed number of values as arguments.
MethodDeclaration: MethodHeader MethodBody MethodHeader: MethodModifiers (opt) ResultType MethodDeclarator Throws (opt) where : ResultType: Type Void MethodDeclarator: Identifier (formal parameter list optional) FormalParameter: Final (opt) Type VariableDeclaratorID
There is a compile-time error
- If the body of a class have two methods with the same signature.
- If two formal parameters of the same method are declared to have the same name, then a compile-time error occurs.
- If a method parameter that is declared final is assigned to within the body of the method.
A constructor is also treated as a method. Parameter names may not be re-declared as local variables of the method, or as exception parameters of catch clauses in a try statement of the method.
Method modifiers are one of the following; if two or more method modifiers appear in a method declaration, it is customary, though not required, that they appear in the order consistent with that shown below
- Public
- Protected
- Private
- Abstract
- Static
- Final
- Synchronized
A compile-time error occurs
- If the same modifier occurs more than once in the method declaration
- If a method declaration has more than one of the access modifiers : public, protected or private.
- If a method declaration contains the keyword abstract and also contains any of the keywords : private, static, final, native or synchronized.
An abstract method declaration introduces the method as a member, providing its signature, return type and throws clause (if any), but does not provide an implementation. A declaration of a abstract method must appear directly within an abstract class, failing which a compile-time error results. An abstract class can override an abstract method by providing another method declaration.
A method that is declared static is always invoked without reference to a particular object. An attempt to reference the current object using the keyword this or the keyword super in the body of a static method results in a compile-time error. A static method cannot be declared abstract. A non-static method can always refer to the current object using the keywords this and super during the execution of the method body.
A method can be declared final to prevent subclasses from overriding or hiding it. A private method and all methods declared in a final class is implicitly final as it is impossible to override them. “A final method cannot be declared abstract. “ A throws clause is used to declare any checked exceptions that can result from the execution of a method. A compile-time error occurs if any class type mentioned in a throws clause is not the class throwable or a subclass throwable.
A method body is either a block of code that implements a method or simply a semi-colon indicating the lack of implementation such as in cases abstract and native methods. If a method is declared void, then its body must not contain any return statement that has a expression. If a method is declared to have return type, then every return statement in its body must have an expression. A class inherits from its direct super class all the non-private methods (whether abstract or not) of the super class that are accessible to code in the class and are neither overridden nor hidden by a declaration in the class.
A class C inherits from its direct superclass and direct superinterfaces all non-private methods (whether abstract or not) of the superclass and superinterfaces that are public, protected or declared with default access in the same package as C and are neither overridden nor hidden by a declaration in the class.
An instance method m1 declared in a class C overrides another instance method, m2, declared in class A iff all of the following are true
- C is a subclass of A.
- The signature of m1 is a subsignature of the signature of m2.
- Either m2 is public, protected or declared with default access in the same package as C, or m1 overrides a method m3, m3 distinct from m1, m3 distinct from m2, such that m3 overrides m2.
Moreover, if m1 is not abstract, then m1 is said to implement any and all declarations of abstract methods that it overrides.
A compile-time error occurs if an instance method overrides a static method. It is a compile time error if a type declaration T has a member method m1 and there exists a method m2 declared in T or a supertype of T such that all of the following conditions hold
- m1 and m2 have the same name.
- m2 is accessible from T.
- The signature of m1 is not a subsignature of the signature of m2.
- m1 or some method m1 overrides (directly or indirectly) has the same erasure as m2 or some method m2 overrides (directly or indirectly).
A constructor is used in the creation of an object that is an instance of a class:
ConstructorDeclaration: ConstructorModifiersopt ConstructorDeclarator Throwsopt ConstructorBody ConstructorDeclarator: TypeParametersopt SimpleTypeName ( FormalParameterListopt )
The SimpleTypeName in the ConstructorDeclarator must be the simple name of the class that contains the constructor declaration; otherwise a compile-time error occurs. In all other respects, the constructor declaration looks just like a method declaration that has no result type.
Constructors are never invoked by method invocation expressions. Access to constructors is governed by access modifiers. Constructor declarations are not members. They are never inherited and therefore are not subject to hiding or overriding. It is a compile-time error to declare two constructors with override-equivalent signatures in a class. A compile-time error occurs if the same modifier appears more than once in a constructor declaration, or if a constructor declaration has more than one of the access modifiers public, protected, and private. Unlike methods, a constructor cannot be abstract, static, final, native, strictfp or synchronized. The throws clause for a constructor is identical in structure and behavior to the throws clause for a method. It is a compile-time error for a constructor to directly or indirectly invoke itself through a series of one or more explicit constructor invocations involving this. Overloading of constructors is identical in behavior to overloading of methods.
An enum declaration has the form:
EnumDeclaration:
ClassModifiersopt enum Identifier Interfacesopt EnumBody
EnumBody:
{ EnumConstantsopt , EnumBodyDeclarationsopt }
The body of an enum type may contain enum constants. An enum constant defines an instance of the enum type. An enum type has no instances other than those defined by its enum constants.
EnumBodyDeclarations: ClassBodyDeclarationsopt
An enum constant may be preceded by annotation modifiers. If an annotation a on an enum constant corresponds to an annotation type T, and T has a (meta-)annotation m that corresponds to annotation target, then m must have an element whose value is annotation.ElementType.FIELD, or a compile-time error occurs.
An enum constant may be followed by arguments, which are passed to the constructor of the enum type when the constant is created during class initialization as described later in this section. The constructor to be invoked is chosen using the normal overloading rules. If the arguments are omitted, an empty argument list is assumed. If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is private.
The optional class body of an enum constant implicitly defines an anonymous class declaration that extends the immediately enclosing enum type. The class body is governed by the usual rules of anonymous classes; in particular it cannot contain any constructors.
