Jump to content




Classic - pretty OOP in CC


38 replies to this topic

#1 Kouksi44

  • Members
  • 89 posts
  • LocationMunich, Germany

Posted 25 March 2016 - 09:24 PM

CLASSIC

What is it ?

Classic is an api that offers users the possibility to use some common features of many oop languages.
That basically means you can use classes that inherit from each other and implement interfaces.

I know there are quite a few pretty similar oop libraries out there, but I haven´t found many that try to implement classes in a way that both looks pretty and is convenient to use.
Therefore I gave it try and finally after a few attempts I came up with this api.

How to use it:

The library allows the usage of two things: Classes and Interfaces.

Let´s look at how you create a simple class:

dofile("classic")

class "Shape" {
  colour;
}

That´s it ! We´ve created a simple class called "Shape" that has a property called "colour".
Anyways we can´t yet create an instance of this class as we still lack a method that serves as a constructor:

class "Shape" {
  colour;
}

function Shape:init(colour)
  self.colour=colour
  print("I am a simple shape !")
end

Now that we´ve added a init function we can create an instance of our class by writing:

local testshape=Shape(colours.red)

Of course we can´t do much with such an abstract "Shape" Object so let´s create a class that is a bit more usefull !

class "Square" extends "Shape" {
  x;
  y;
  width;
  height;
}

function Square:init(x,y,width,height,colour)
  self.x=x
  self.y=y
  self.width=width
  self.height=height
  self.colour=colour
end

As you can see the "Square" class inherits all properties from Shape by extending the class.

The last feature , this library has to offer are interfaces.
Interfaces are a basically classes without an init function:


interface "ITalk" {
  talk=function(self,text)
	print(self.name.." says :"..text)
  end;
}

class "Human" implements "ITalk" {
  ...
}

Every "Person" can now use the function talk to say something !
Of course you can also inherit from a class and implement an interface at the same time :
class "Male" extends "Human" implements "ITalk" {
  ...
}

Some further details:
Spoiler

ToDo:
Spoiler


Download:
Pastebin:
 pastebin get MfsdVz6U classic 

Let me know if there are any bugs or errors with this library !

Edited by Kouksi44, 12 September 2016 - 07:49 PM.


#2 Dahknee

  • Members
  • 1,808 posts
  • Location/home/da

Posted 27 June 2016 - 05:58 PM

I can't believe no one has commented, can I just say great work, this is a really nice to use library and I do use it a lot, is there a way you can make it so it's loadable as an API instead of using dofile?

My only query is I think you have the wrong concept of interfaces as I use them in PHP applications, and they are defined as below:
http://stackoverflow...ted-programming

#3 SquidDev

    Frickin' laser beams | Resident Necromancer

  • Members
  • 1,427 posts
  • LocationDoes anyone put something serious here?

Posted 27 June 2016 - 06:02 PM

View PostDannySMc, on 27 June 2016 - 05:58 PM, said:

My only query is I think you have the wrong concept of interfaces as I use them in PHP applications, and they are defined as below:
Generally interfaces with a default definition are known as traits. How does it handle multiple interfaces with the same method name?

#4 Dahknee

  • Members
  • 1,808 posts
  • Location/home/da

Posted 27 June 2016 - 06:05 PM

View PostSquidDev, on 27 June 2016 - 06:02 PM, said:

View PostDannySMc, on 27 June 2016 - 05:58 PM, said:

My only query is I think you have the wrong concept of interfaces as I use them in PHP applications, and they are defined as below:
Generally interfaces with a default definition are known as traits. How does it handle multiple interfaces with the same method name?

Not quite got to that, just writing a basic proof of concept program, to see how powerful it is, and I guess, but in PHP they are used to define inputs and outputs that's all, well with the frameworks I use, so apologies as I am mainly basing it off PHP.

#5 Kouksi44

  • Members
  • 89 posts
  • LocationMunich, Germany

Posted 27 June 2016 - 11:16 PM

View PostDannySMc, on 27 June 2016 - 05:58 PM, said:

I can't believe no one has commented, can I just say great work, this is a really nice to use library and I do use it a lot, is there a way you can make it so it's loadable as an API instead of using dofile?

My only query is I think you have the wrong concept of interfaces as I use them in PHP applications, and they are defined as below:
http://stackoverflow...ted-programming

Glad you like it ! I didn't really have any spare time to code in the last months, but there will definitely be an update to this library in the near future.

Adding support for os.loadApi shouldn't be too hard, it was simply more convenient for me to use dofile() as I could test my library directly in my editor that way.

The next update will probably contain a few other changes aswell:
- members can be declared as private and public
- members can be declared as static and final
- objects can be serialized and rebuilt

#6 jv110

  • Members
  • 108 posts
  • LocationIn front of my PC

Posted 28 June 2016 - 03:13 AM

I gotta say, your "method chain" method is brilliant. I'd never have thought of that.

#7 Dahknee

  • Members
  • 1,808 posts
  • Location/home/da

Posted 28 June 2016 - 09:27 AM

View PostKouksi44, on 27 June 2016 - 11:16 PM, said:

View PostDannySMc, on 27 June 2016 - 05:58 PM, said:

I can't believe no one has commented, can I just say great work, this is a really nice to use library and I do use it a lot, is there a way you can make it so it's loadable as an API instead of using dofile?

My only query is I think you have the wrong concept of interfaces as I use them in PHP applications, and they are defined as below:
http://stackoverflow...ted-programming

Glad you like it ! I didn't really have any spare time to code in the last months, but there will definitely be an update to this library in the near future.

Adding support for os.loadApi shouldn't be too hard, it was simply more convenient for me to use dofile() as I could test my library directly in my editor that way.

The next update will probably contain a few other changes aswell:
- members can be declared as private and public
- members can be declared as static and final
- objects can be serialized and rebuilt

That's fine, well I would say you need to keep updating it and make it loadable via API!! As I want to use this in my main API for my programs, as this would be super useful.

But honestly really nice implementation, very clean, definitely one of my favourite implementations, as some people over complicate it too much I guess? and make it very bulky, this is small and clean. It's nice :P

#8 Kouksi44

  • Members
  • 89 posts
  • LocationMunich, Germany

Posted 28 June 2016 - 03:36 PM

Small update:

As far as I have tested it, loading the library through os.loadApi should work now.

Additionally, I have added some new features :
  • Members can now be made private or public ( public does not really differ from the normal way of defining members )
  • Members can now be made final so that their initial value can't be modified
Examples

Modifying members:

class "Example" {
   exampleValue = private - final - "Hello World";
}

local obj = Example()


As you can see, modifiers are put in front of the value of the member. They can be chained by separating them with "-".

In this example the value of exampleValue couldn't be changed and not be accessed from outside the Example class.

The pastebin link is still the same so simply run the install command once again !

If you find any bugs report them here !

Edited by Kouksi44, 28 June 2016 - 04:03 PM.


#9 Dahknee

  • Members
  • 1,808 posts
  • Location/home/da

Posted 28 June 2016 - 04:31 PM

View PostKouksi44, on 28 June 2016 - 03:36 PM, said:

Small update:

As far as I have tested it, loading the library through os.loadApi should work now.

Additionally, I have added some new features :
  • Members can now be made private or public ( public does not really differ from the normal way of defining members )
  • Members can now be made final so that their initial value can't be modified
Examples

Modifying members:

class "Example" {
   exampleValue = private - final - "Hello World";
}

local obj = Example()


As you can see, modifiers are put in front of the value of the member. They can be chained by separating them with "-".

In this example the value of exampleValue couldn't be changed and not be accessed from outside the Example class.

The pastebin link is still the same so simply run the install command once again !

If you find any bugs report them here !



Hmm nice update, I would suggest seeing if you can get it to work as:

public function foo()

for variables and functions :P

#10 Kouksi44

  • Members
  • 89 posts
  • LocationMunich, Germany

Posted 28 June 2016 - 05:18 PM

Hm I'm pretty sure that I won't be able to implement that kind of syntax.
 public function foo() 
I have no idea how to make public work in front of the function keyword without any metatable magic.

However I will try adding static members so that all instances of a class share that value !

#11 Dahknee

  • Members
  • 1,808 posts
  • Location/home/da

Posted 29 June 2016 - 12:33 PM

View PostKouksi44, on 28 June 2016 - 05:18 PM, said:

Hm I'm pretty sure that I won't be able to implement that kind of syntax.
 public function foo() 
I have no idea how to make public work in front of the function keyword without any metatable magic.

However I will try adding static members so that all instances of a class share that value !

Awesome okay!! :D

#12 Kouksi44

  • Members
  • 89 posts
  • LocationMunich, Germany

Posted 29 June 2016 - 08:50 PM

Next update:

Members can now be defined as shared - those members will share their values across all instances of a class.

Example:
class "SharedTest" {
   test = public - shared - "Hello World";
}

local first = SharedTest()
local second = SharedTest()

first.test="World Hello"
print(second.test)

Even though we only set the member of first to "World Hello" printing the value of the member of second will result in the same string being printed.

Let me know about any bugs with this new update !

#13 unnamedcoder

  • Members
  • 23 posts

Posted 30 June 2016 - 09:39 PM

nice, gives a lot of functionality that vanilla lua doesn't offer, almost as flexible as java

#14 michty

  • Members
  • 4 posts

Posted 02 July 2016 - 02:23 AM

I must say, good work. I was looking for something like this for quite some time. I really missed OOP in LUA!

#15 Kouksi44

  • Members
  • 89 posts
  • LocationMunich, Germany

Posted 03 July 2016 - 05:54 PM

Next update:

This update introduces a (IMO) pretty cool feature !
Members can now be declared to have certain datatypes so e.g. trying to set a member that was declared to hold only tables to anything else than a table will result in an error.

Example:
class "TestClass" {
  member = boolean - true
}

local obj = TestClass()
obj.member = "Hello World"  -- This will error !

This member can only be set to a value that is also boolean OR a nil value !

The only thing you have to keep in mind is, that lua already uses the string and table indexes.
Therefore if you want to define a string or table member you have to write "String" or "Table".

Besides the common lua types ( function, string, table, boolean, number and thread ) there are so called ClassTypes:
You can declare members to only hold objects of a certain class if the class has been defined previously.

Example:
class "Vector" {
  -- ...
}

class "TestClass" {
  member = Vector - Vector()
}

This update might have introduced a few bugs as it changed a lot of code in the background so let me know if anything seems to be broken !

Edit: Forgot to mention that ClassTypes basically check if the class of the given object equals the predefined ClassType or is atleast a subclass of that class!

Edited by Kouksi44, 03 July 2016 - 06:25 PM.


#16 thecrimulo

  • Members
  • 87 posts
  • Locationhere

Posted 05 July 2016 - 05:04 PM

I can use it as an API while I dofile() Classic? For example, making a shape class, and using it in other file, using dofile("classic") and dofile("myapi")

#17 Kouksi44

  • Members
  • 89 posts
  • LocationMunich, Germany

Posted 05 July 2016 - 05:31 PM

If you want to use a class that is defined in another file you can import that class by calling:
 using "path.to.the.class" 

Note that "." is used instead of "/" in the path

#18 Lupus590

  • Members
  • 2,029 posts
  • LocationUK

Posted 05 July 2016 - 07:12 PM

View PostKouksi44, on 05 July 2016 - 05:31 PM, said:

If you want to use a class that is defined in another file you can import that class by calling:
 using "path.to.the.class" 

Note that "." is used instead of "/" in the path

any way to allow "/" instead of "." ?
why do you have to use "." ?

#19 Exerro

  • Members
  • 801 posts

Posted 05 July 2016 - 08:07 PM

View PostLupus590, on 05 July 2016 - 07:12 PM, said:

View PostKouksi44, on 05 July 2016 - 05:31 PM, said:

-snip-

any way to allow "/" instead of "." ?
why do you have to use "." ?

Lua's require() uses ".", and I personally prefer it as it's more namespacey and less path/to/file-ey.

On the topic of the library:

This is awesome! It's really similar to how I did classes in Sheets, so naturally I'd think it has nice syntax and functionality. However, this has the added benefit of the magic metatable stuff for giving properties to fields of the class, which I have to admit is really clever and looks almost native.

My one real reservation is the name 'init' for the constructor. I've wanted to use a function called 'init' to initialise various things of a class in the past, so I think it'd be much better to use the name of the class as a constructor (i.e. Button:Button() not Button:init()).

#20 Kouksi44

  • Members
  • 89 posts
  • LocationMunich, Germany

Posted 05 July 2016 - 09:17 PM

View PostExerro, on 05 July 2016 - 08:07 PM, said:

View PostLupus590, on 05 July 2016 - 07:12 PM, said:

View PostKouksi44, on 05 July 2016 - 05:31 PM, said:

-snip-

any way to allow "/" instead of "." ?
why do you have to use "." ?

Lua's require() uses ".", and I personally prefer it as it's more namespacey and less path/to/file-ey.

On the topic of the library:

This is awesome! It's really similar to how I did classes in Sheets, so naturally I'd think it has nice syntax and functionality. However, this has the added benefit of the magic metatable stuff for giving properties to fields of the class, which I have to admit is really clever and looks almost native.

My one real reservation is the name 'init' for the constructor. I've wanted to use a function called 'init' to initialise various things of a class in the past, so I think it'd be much better to use the name of the class as a constructor (i.e. Button:Button() not Button:init()).

Glad you like it!

A previous version of classic used the classname for the constructor but I think i changed it because I thought it looked a bit weird to write a function called
 function Button:Button () 

However I might change this again in the next update.

One thing I just realized :

Right now, you should avoid using ClassTypes or declaring class members that hold Objects in general.
Accessing those members won't work as copying those Objects once the class instance is created is a bit buggy.

Edited by Kouksi44, 05 July 2016 - 09:13 PM.






1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users