Text not verified for kermeta 2 | |
---|---|
As introduced in the "Hello world" example (see Section 1.2.1, “ First Program ” ), Kermeta is an object-oriented language. Kermeta provides all MOF concepts like properties, attributes, package. In addition, it provides a body to operations and derived properties.
Classes and abstract classes can be defined in a Java-like way. Class definition must be placed into brackets as it is in the following example.
// an empty simple class class myFirstClass { } // a simple abstract class abstract class MyAbstractClass { }
Additionally, for better code robustness, and more user-friendly programming, classes can use the genericity mechanisms (see Section 2.10, “ Genericity ” for more information).
// This is a parametric class class A<G> { } // This is the type variable binding : G is binded with Integer var a : A<Integer> a := A<Integer>.new
There are some limitations in regards to Java. For example, you cannot define nested classes in Kermeta. Kermeta offers the same structural concepts than MOF language.
Kermeta provides a way to add operational (action) semantics to your metamodels. For that, you can define operations with their body, as in a classical programming language. You can also specify abstract operations (they have no body). Kermeta requires that every class that contains an abstract operation must be declared as an abstract class.
In the following example, we define some operations, based on a visitor pattern implementation
class Inventory { operation visitLibrary(l : Library) is do writeln("Inventory : "); l.books.each(b : Book | b.accept(self)) writeln("----") end operation visitBook(b : Book) is do stdio.write("Book : ", b.title, " by ") b.authors.each(a : Author | a.accept(self)) end operation visitAuthor(a : Author) is do stdio.write(a.name, " ", a.lastName) end } class Library { // ... operation accept(visitor : Inventory) is do visitor.visitLibrary(self) end } class Book { // ... operation accept(visitor : Inventory) is do visitor.visitBook(self) end } class Author { // ... operation accept(visitor : Inventory) is do visitor.visitAuthor(self) end }
In this small example we define an
Inventory
class which can go over the library structure and print books
informations. For that, we apply
the visitor GoF pattern's on the
library structure defining an
accept
method in
every library structures.
The special variable
result
is used to
store the value that will be returned by the operation.
operation getName() : String is do result := self.name end
Note | |
---|---|
This is different of the
|
When you run a Kermeta program you'll start from an operation. The main operation that you want to run can have any number of parameters, whose types must be only and only String. For operations that are not intended to be run, you can put any type of parameters.
Technically, if you use Kermeta inside Eclipse, when you will ask it to run your operation, the interpreter will implicitely instanciate the class containing this operation, and then will call this operation.
Example : 3 different kinds of "runnable" operations
class A{ operation main0() is do // do something end operation main1( arg1 : String) is do // do something with 1rst argument end operation main3( arg1 : String, arg2 : String) is do // do something with 1st and 2nd arguments end } // If you ask to launch main0, Kermeta interpereter will create an instance of A and will run main0 on it.
Kermeta doesn't use constructors.
However in some situation, you may need to provide some initialization operation. The best approach is simply to declare an operation which will return self after having done the initialization work.
class A { attribute name : String operation initialize(name : String) : A is do self.name := name end }
// now you can use it easily in one line var aA : A init A.new.initialize("hello")
Here are some explanation about some design choice of Kermeta classes.
This is because of the compatibility with EMOF and Ecore. In those metalanguages, the user must always be able to create object (except if they are declared abstract), it cannot rely on a action language (since they don't define one). In addition, we want that all Meta tool be able to create the object the same way, so, as Ecore doesn't provide constructor with its editors, then neither does Kermeta.
However, you can easily add an
init
or
myInitialize
operation that will
take as many parameters as you want. Even
better, you can use a
Builder or a
Factory design pattern.
aspect class ClassFromMyEcore { operation init(myParam : String) : ClassFromMyEcore is do // assign myParam to some attribute self.name := myParam // return self for easier use result := self end // now you can create and initialize this class in one line // var foo : ClassFromMyEcore init ClassFromMyEcore.new.init("foo") }