Wish Object-oriented programming to B4X: Inheritance + Polymorphism

DonManfred

Expert
Licensed User
Longtime User

b4auser1

Well-Known Member
Licensed User
Longtime User
Page is empty.

I don't think that inheritance will ever be added to the language.
It's difficult to implement or there are other reasons ?

Polymorphism is supported through the usage of CallSub (duck typing).
I use CallSub as all other B4X developers very widely. But there are problems with not checking types compatibilty at compilation phase

https://www.b4x.com/android/forum/t...t-warnings-if-types-are-not-compatible.64341/

It's not just due to using of CallSub of course.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User

wonder

Expert
Licensed User
Longtime User
I offer to add to B4x Inheritance + Polymorphism.
+1

In my opinion have the possibility to do something like this could make B4X the best language ever for mobile game development!
B4X:
class GameCharacter
{
    public:
        virtual void attack() { std::cout << "The opponent attacks."; }
}

class Knight : public GameCharacter
{
    public:
        void attack() { std::cout << "The knight thrusts his sword."; }
}

class Archer : public GameCharacter
{
    public:
        void attack() { std::cout << "The archer fires an arrow."; }
}


The current state of affairs is not a deal breaker, but the kind of solutions I have to use aren't the most elegant:
B4X:
'Class module: GameCharacter
Sub Process_Globals
    ...
    Dim KNIGHT = 1 As Int
    Dim ARCHER = 2 As Int
    ...
End Sub

Sub Attack(category as Int)
    Select category
        Case KNIGHT
            Log("The knight thrusts his sword.")

        Case ARCHER
            Log("The archer fires an arrow.")

        Case Else
            Log("The opponent attacks.")

    End Select
End Sub
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
This is not the "correct" implementation in B4X.

Better:
B4X:
'GameCharacter class
Sub Class_Globals
   Public mName As String
End Sub

Public Sub Initialize (name As String)
   mName = name
End Sub

'Archer class
Sub Class_Globals
   Private gc As GameCharacter
End Sub

Public Sub Initialize (name As String)
   gc.Initialize(name)
End Sub

Public Sub Attack
   Log($"${gc.mName} the archer fires an arrow"$)
End Sub

'Knight class
Sub Class_Globals
   Private gc As GameCharacter
End Sub

Public Sub Initialize (name As String)
   gc.Initialize(name)
End Sub

Public Sub Attack
   Log($"${gc.mName} the brave knight thrusts his sword."$)
End Sub

'main module (b4j - non-ui):
Sub Process_Globals
   Private characters As List
End Sub

Sub AppStart (Args() As String)
   characters.Initialize
   For i = 1 To 100
     If Rnd(0, 2) = 0 Then
       Dim k As Knight
       k.Initialize("k" & i)
       characters.Add(k)
     Else
       Dim a As Archer
       a.Initialize("a" & i)
       characters.Add(a)
     End If
   Next
   For Each c As Object In characters
     CallSub(c, "Attack") 'duck typing
   Next
End Sub


You need to add all the shared logic to GameCharacter.
 

b4auser1

Well-Known Member
Licensed User
Longtime User
I use the approach described by Erel widely.
There is a small inconvenience if there is more than one level of Inheritance. Class B includes A. Class C includes B and etc.
To achieve methods or properties of base class it's necessary to use several points.
cObject.bObject.aObject.Method
or repeat implementation of all methods of base class in the Inheritor class.
 

Roberto P.

Well-Known Member
Licensed User
Longtime User
I think it would be great improvement for Tools B4X have the ability to have inheritance (both objects and interfaces).

For me, it is the only big limit present in various tools, particularly in B4A. This results in duplication of code for objects that are very similar and that could result from a common object basis.

Erel, it would be great to create objects "outside B4X", in Java, and be able to derive the B4X classes from these classes.

I hope it's been helpful ...

Greetings :)
 

Dave O

Well-Known Member
Licensed User
Longtime User
@Erel, you mention that "You need to add all the shared logic to GameCharacter".

From outside the classes (e.g. from AppStart), how would you call methods that are defined in the GameCharacter base class?

For example, if the GC class had a vanilla Hello method (used by the Knight and Archer classes without customization), how would you call Hello from AppStart? Can it be made visible and callable directly, or would you need to implement a Hello method in the Knight and Archer classes that then called gc.Hello?

(I'm writing a poker app that will have several types of players (e.g. stupid, average, smart), and I'm trying to decide how to model the classes and methods for them, without endless Select Case blocks. If I can use composition instead of inheritance or interfaces, that sounds promising.)

Thanks!
 

Toky Olivier

Active Member
Licensed User
Longtime User
B4X++ — A Proof of Concept for OOP-style B4X Library Development

Hi everyone,

I would like to introduce B4X++, a small proof-of-concept project that explores how more advanced OOP-style features could be used when writing B4X code, especially for developers creating B4XLib libraries.

GitHub repository:
https://github.com/soinalastudio/B4XPP

First of all, I want to be very clear: B4X++ is not intended to replace the B4X IDEs, and it is not a definitive proposal for changing the B4X language.

I fully understand that one of the strengths of B4X is its simplicity, and that we do not necessarily want to overload the language with too many new keywords or concepts.

The idea is rather similar to TypeScript generating JavaScript:
B4X++ code would be written with some additional syntax, then precompiled into standard B4X code that can be opened, compiled, and used normally in the existing B4X IDEs.

The main goal is to experiment with features that could be useful for library authors, especially when building reusable components where there is often a lot of repeated code.

For example, B4X++ currently explores concepts such as:

  • #Extends
  • #Override
  • Super.Method
  • #Property
  • inherited designer properties
  • inherited events
  • generation of flattened .bas files compatible with normal B4X projects
To demonstrate the idea, I included a simple Animals example written in B4X++, showing how inheritance and overrides could help structure code in a cleaner way.

I also attached a more concrete example: B4XAnalogClock, converted as a B4X++ experiment and generated as a compilable B4XLib project, directly usable from standard B4X.
1782556917919.png

B4XClockDrawable.bx:
#Interface B4XClockDrawable
Public Sub Draw(Canvas As B4XCanvas, CenterX As Float, CenterY As Float, Radius As Float)
#End Interface

B4XClockDrawableBase.bx:
#Class B4XClockDrawableBase Abstract

#Property Visible As Boolean = True
#Property Color As Int = 0xFF000000

Sub Class_Globals
End Sub

Public Sub Initialize
End Sub

Virtual Sub Draw(Canvas As B4XCanvas, CenterX As Float, CenterY As Float, Radius As Float)
End Sub

#End Class

B4XClockHand.bx:
#Class B4XClockHand Extends B4XClockDrawableBase

#Property AngleDegrees As Float = 0
#Property LengthRatio As Float = 0.70
#Property TailRatio As Float = 0.08
#Property HandWidth As Float = 3

Sub Class_Globals
    Private mKind As String
End Sub

Public Sub Initialize(Kind As String)
    Super.Initialize
    mKind = Kind
End Sub

Override Sub Draw(Canvas As B4XCanvas, CenterX As Float, CenterY As Float, Radius As Float)
    If mVisible = False Then Return
    Dim r1 As Float = Radius * mLengthRatio
    Dim r2 As Float = Radius * mTailRatio
    Dim x1 As Float = B4XClockMath.PointX(CenterX, r1, mAngleDegrees)
    Dim y1 As Float = B4XClockMath.PointY(CenterY, r1, mAngleDegrees)
    Dim x2 As Float = B4XClockMath.PointX(CenterX, -r2, mAngleDegrees)
    Dim y2 As Float = B4XClockMath.PointY(CenterY, -r2, mAngleDegrees)
    Canvas.DrawLine(x2, y2, x1, y1, mColor, mHandWidth)
End Sub

Public Sub getKind As String
    Return mKind
End Sub

#End Class

B4XClockHourHand.bx:
#Class B4XClockHourHand Extends B4XClockHand Final

#Constructor
    Super.Initialize("hour")
    mLengthRatio = 0.48
    mTailRatio = 0.06
    mHandWidth = 5dip
#End Constructor

#End Class

B4XClockMinuteHand.bx:
#Class B4XClockMinuteHand Extends B4XClockHand Final

#Constructor
    Super.Initialize("minute")
    mLengthRatio = 0.68
    mTailRatio = 0.08
    mHandWidth = 3dip
#End Constructor

#End Class


Again, this is still very early and should be considered only as a proof of concept. Nothing is final, and the syntax or implementation may change completely.

My main objective is to explore whether this kind of precompiler could help B4X library developers avoid repetition, improve code organization, and build larger reusable components more comfortably, while still keeping the final output fully compatible with the existing B4X ecosystem.

I would be very interested to hear your thoughts, suggestions, criticism, or ideas.

Thanks!
 

Attachments

  • B4XAnalogClock-B4X++ Library Example.zip
    9.8 KB · Views: 2
  • B4XPPShowcase.zip
    6.8 KB · Views: 2
  • AnimalDemo.zip
    5.6 KB · Views: 2
  • B4XAnalogClock.zip
    4 KB · Views: 2
  • B4XAnalogClock.b4xlib
    44.9 KB · Views: 2
Top