Inner classes: Difference between revisions

Added FreeBASIC
(J)
(Added FreeBASIC)
 
(5 intermediate revisions by 3 users not shown)
Line 165:
</pre>
 
=={{header|FreeBASIC}}==
{{trans|Go}}
FreeBASIC is not an object-oriented programming language and does not have support for internal classes. However, you can simulate some features of object-oriented programming using Type and Sub.
<syntaxhighlight lang="vbnet">Type Inner
campo As Integer
End Type
 
Type Outer
campo As Integer
interno As Inner
End Type
 
Sub outerMethod(o As Outer)
Print "Outer's field has a value of "; o.field
End Sub
 
Sub innerMethod(o As Outer)
Print "Inner's field has a value of "; o.interno.field
End Sub
 
Dim As Outer o
o.field = 43
o.interno.field = 42
innerMethod(o)
outerMethod(o)
 
Dim As Outer p
p.field = 45
p.interno.field = 44
innerMethod(p)
outerMethod(p)
 
Sleep</syntaxhighlight>
{{out}}
<pre>Same as Go entry.</pre>
 
=={{header|Go}}==
Go supports some aspects of OO albeit in an unorthodox manner:
 
* Structs are used rather than classes.
* Any methods are always defined outside the struct itself but within the containing package.
* Struct fields are never private to the struct itself though, unless they begin with an upper case letter, they are private to the containing package.
* Structs do not support inheritance - composition can be used instead.
* Polymorphism is supported to some extent via the use of interfaces.
 
It is possible to nest structs as the following example shows. However, the problem here is that the nested struct has an anonymous type and the only way to give it methods is via an instance of the Outer struct.
 
In practice it would probably be better to declare the nested struct independently but within the same package and achieve encapsulation by restricting the package to just those two structs.
<syntaxhighlight lang="go">package main
 
import "fmt"
 
type Outer struct {
field int
Inner struct {
field int
}
}
 
func (o *Outer) outerMethod() {
fmt.Println("Outer's field has a value of", o.field)
}
 
func (o *Outer) innerMethod() {
fmt.Println("Inner's field has a value of", o.Inner.field)
}
 
func main() {
o := &Outer{field: 43}
o.Inner.field = 42
o.innerMethod()
o.outerMethod()
/* alternative but verbose way of instantiating */
p := &Outer{
field: 45,
Inner: struct {
field int
}{
field: 44,
},
}
p.innerMethod()
p.outerMethod()
}</syntaxhighlight>
 
{{out}}
<pre>
Inner's field has a value of 42
Outer's field has a value of 43
Inner's field has a value of 44
Outer's field has a value of 45
</pre>
 
=={{header|J}}==
 
J allows inner classes, but because such classes are always public,
there is little or no utility to be had, nesting classes in J.
 
Class definition for task:
Line 255 ⟶ 347:
main()
</syntaxhighlight>
 
=={{header|Phix}}==
Phix has no support whatsoever for inner classes. You can of course do something like this:
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (classes)</span>
<span style="color: #008080;">class</span> <span style="color: #000000;">inner</span>
<span style="color: #008080;">public</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">v</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">is</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">+</span><span style="color: #7060A8;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">v</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">class</span>
<span style="color: #008080;">class</span> <span style="color: #000000;">outer</span>
<span style="color: #008080;">public</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">v</span>
<span style="color: #008080;">public</span> <span style="color: #000000;">inner</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">ois</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">inner</span> <span style="color: #000000;">ti</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">this</span><span style="color: #0000FF;">.</span><span style="color: #000000;">i</span> <span style="color: #000080;font-style:italic;">-- (a needed compiler hint)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">ti</span><span style="color: #0000FF;">.</span><span style="color: #000000;">is</span><span style="color: #0000FF;">(</span><span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">class</span>
<span style="color: #000000;">outer</span> <span style="color: #000000;">o</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new</span><span style="color: #0000FF;">({</span><span style="color: #000000;">42</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">new</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inner</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})})</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">o</span><span style="color: #0000FF;">.</span><span style="color: #000000;">v</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">o</span><span style="color: #0000FF;">.</span><span style="color: #000000;">i</span><span style="color: #0000FF;">.</span><span style="color: #000000;">v</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">o</span><span style="color: #0000FF;">.</span><span style="color: #000000;">v</span><span style="color: #0000FF;">+</span><span style="color: #000000;">o</span><span style="color: #0000FF;">.</span><span style="color: #000000;">i</span><span style="color: #0000FF;">.</span><span style="color: #000000;">v</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">o</span><span style="color: #0000FF;">.</span><span style="color: #000000;">ois</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
A shown, Phix often needs explicit compiler hints when dealing with classes, without "ti" above it treats "this.i" as still somehow being an "outer", and admittedly there is no real access to outer's contents within inner. Instead you would need shims like that ois() to explicitly pass along everything it needs.<br>
It is also possible to pass routines around directly, such as i.is and o.ois [ie no parenthesis] and then invoke them with an explicit "this", which can get round some of those limitations, and act as an alternative to those compiler hints.
{{out}}
<pre>
42
1
43
43
</pre>
 
=={{header|Raku}}==
Line 298 ⟶ 426:
 
To make things a little more interesting the inner class in the following example also inherits from the outer class. In fact inheritance is the only way for the inner class to access the outer class's instance methods ''directly'' as it is otherwise treated the same as a non-nested class. The only advantage it really offers is to encapsulate closely related classes under the one umbrella .
<syntaxhighlight lang="ecmascriptwren">class Outer {
static makeInner {
class Inner is Outer {
2,122

edits