The output of the below code was-
This is class A
This is class A
But according to me the output should be-
This is class A
This is Extended class A
Because, after printing the first line, we are assigning object of type EA to object of type A-
EA my_a = my_ea;
and then when we do-
my_a.disp();
it should print-This is Extended class A
Please tell whether I am correct or not?
class A ; //class A
task disp ();
$display(" This is class A ");
endtask
endclass
class EA extends A ; //subclass EA
task disp ();
$display(" This is Extended class A ");
endtask
endclass
program main ;
EA my_ea;
A my_a;
initial
begin
my_a = new();
my_a.disp();
my_ea = new();
my_a = my_ea;
my_a.disp();
end
endprogram
You need to declare the task as virtual:
class A ; //class A
virtual task disp ();
$display(" This is class A ");
endtask
endclass
Related
I have the following code:
// irrelevant code ...
type
Zombie = class
private
...
Age : Integer;
Alive : Boolean;
TotalDeadZombies, TotalZombieAge : Double;
public
...
procedure ZombieGrow();
procedure CheckIfDead();
...
Function AvgLife() : Double;
end;
procedure Zombie.ZombieGrow();
begin
...
if (Alive = false) then
begin
TotalDeadZombies := TotalDeadZombies + 1;
TotalZombieAge := TotalZombieAge + Age;
end;
end;
procedure Zombie.CheckIfDead();
begin
if Random(100) < 20 then
Alive := False;
end;
function Zombie.AvgLife() : Double;
begin
Result := TotalZombieAge / TotalDeadZombie;
end;
The problem I have is I want to display the average age of dead zombies. This would be done via something like :
Write('Average age '+Floattostr(Round(AvgLife)))
However, this is called in another class (not shown here), and from my understanding of OOP, it would require me to specify an instantiated object, e.g zombies[1].AvgLife if they were stored in, say, a Zombies[] array (just an example).
Is there a way of making it so the variables TotalDeadZombies and TotalZombieAge are not tied to any instantiated zombies, but rather to a class variable that I can then just call AvgLife somehow? Is it as simple as just making them global variables? Or can it be done another way?
You just have to declare the variables as class var; then they belong to the class, and not to a particular instance of a class.
type
TZombie = class
public
class var TotalDeadZombies, TotalZombieAge: Double;
end;
You can access these like TZombie.TotalDeadZombies. Similarly, there are class methods, class properties, etc.
Have a look at the official documentation.
I am having an issue with Pascal-Lazarus (Linux):
The class methods can't acces the members. It isn't a compiler mistake, but a runtime error. (SIGSEV)
For more informations: i am using Linux with the newest version (16_4) and Lazarus Pascal (16.0). My system type is x86_64
the code:
unit compiler_code;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
TLine = class
public //public methods
procedure setLine(i: string); //setter for the line.
procedure compileLine(); //just runs the different methods of the class
private //private members
var m_string : string;
var m_stringLength : integer;
private //private methods
function deleteBlanks (i: string) : string;
procedure getStringLength();
end;
var Form1: TForm1;
var Zeile: TLine;
implementation
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
Zeile.setLine ('Hallo');
Zeile.compileLine ();
end;
/////////////////////////Implementation of the Methods of TLine
procedure TLine.setLine(i: string); //Setter --> no getter needed.
begin
showmessage (i);
showmessage (m_string); //here is where the issue comes up
//m_string:= i;
end;
procedure TLine.compileLine(); //runs all of the Methods.
begin
getStringLength (); // gets the length of the String-input
m_string := deleteBLanks(m_string); //deletes all of the blank space inside the String.
end;
function TLine.deleteBlanks (i: string) : string; //blankSpace-Deleter
var isText : boolean = false; //switch, to check, if the momentary Character is text or not.
var counter: integer = 0; //counts the number of cycles of the loop
begin
while ((counter < m_stringLength) and (not (m_stringLength = 0))) do //the 'Loop'
begin
if ((m_string[counter] = ' ') and (not(isText))) then
begin
delete (m_string, counter, 1); //deletes the blank position
dec (counter); //because there is a position less in the string now.
getStringLength(); //regenerates the length of the String;
end;
end;
end;
procedure TLine.getStringLength ();
begin
m_stringLength:= length (m_string); //gets the Length of the String input.
end;
{$R *.lfm}
end.
The explanation is, presumably, that you simply have not created an instance of the class TLine. Nowhere do you assign to Zeile and so it remains at its default value of nil.
You need to instantiate an instance
Zeile := TLine.Create;
You must do this before you attempt to reference Zeile. When you are done with the instance, destroy it:
Zeile.Free;
I looked at the following code on Rosetta code http://rosettacode.org/wiki/Singleton#Perl_6
which implements Singleton in Perl6
class Singleton {
has Int $.x is rw;
# We create a lexical variable in the class block that holds our single instance.
my Singleton $instance = Singleton.bless; # You can add initialization arguments here.
method new {!!!} # Singleton.new dies.
method instance { $instance; }
}
my $a=Singleton.bless(x => 1);
my $b=Singleton.bless(x=> 2);
say $a.x;
say $b.x;
#result
# 1
# 2
but it seems using this implementation i can create tow instances of the same class using bless see example above ,
is there an option to prevent the implemention to only one instance of the same class ?
Perl prides itself on providing many ways to do things leaving you to pick the one that suits your tastes and the application at hand. I say that to highlight that this is one simple but solid, hopefully self-explanatory way - I'm not putting it forward as "the best" because that depends on your circumstances.
#!/usr/bin/env perl6
class Scoreboard {
has Str $.home-team ;
has Str $.away-team ;
has Int $.home-score = 0 ;
has Int $.away-score = 0 ;
my Scoreboard $instance;
method new(*%named) {
return $instance //= self.bless(|%named) ;
}
multi method goal($team where * eq $!home-team, Int :$points = 6) {
$!home-score += $points
}
multi method goal($team where * eq $!away-team, Int :$points = 6) {
$!away-score += $points
}
method Str {
"At this vital stage of the game " ~
do given $!home-score <=> $!away-score {
when More {
"$!home-team are leading $!away-team, $!home-score points to $!away-score"
}
when Less {
"$!home-team are behind $!away-team, $!home-score points to $!away-score"
}
default {
"the scores are level! $!home-score apeice!"
}
}
}
}
my $home-team = "The Rabid Rabbits";
my $away-team = "The Turquoise Turtles"; # Go them turtles!
my $scoreboard = Scoreboard.new( :$home-team , :$away-team );
$scoreboard.goal($home-team, :4points) ;
say "$scoreboard";
$scoreboard.goal($away-team) ;
say "$scoreboard";
my $evil_second_scoreboard = Scoreboard.new;
$evil_second_scoreboard.goal($home-team, :2points) ;
say "$evil_second_scoreboard";
This produces;
At this vital stage of the game The Rabid Rabbits are leading The Turquoise Turtles, 4 points to 0
At this vital stage of the game The Rabid Rabbits are behind The Turquoise Turtles, 4 points to 6
At this vital stage of the game the scores are level! 6 apeice!
This overrides the default new (normally supplied by class Mu) and keep a reference to ourself (ie this object) in private class data. For private class data, we use a lexically scoped scalar declared with my. The // is the operator form of .defined. So, on the first run, we call bless which allocates the object and initialize the attributes, and then assign it to $instance. In subsequent calls to new, $instance is defined and is immediately returned.
If you want to prevent someone calling bless directly, you can add;
method bless(|) {
nextsame unless $instance;
fail "bless called on singleton Scoreboard"
}
which will ensure that only the first call will work.
Dont know what this oop pattern is called but how can I do the same pattern in Ada?
For example this code:
interface Vehicle{
string function start();
}
class Tractor implements Vehicle{
string function start(){
return "Tractor starting";
}
}
class Car implements Vehicle{
string function start(){
return "Car starting";
}
}
class TestVehicle{
function TestVehicle(Vehicle vehicle){
print( vehicle.start() );
}
}
new TestVehicle(new Tractor);
new TestVehicle(new Car);
my failed attempt in Ada:
How to fix it properly?
with Ada.Text_IO;
procedure Main is
package packageVehicle is
type Vehicle is interface;
function Start(Self : Vehicle) return String is abstract;
end packageVehicle;
type Tractor is new packageVehicle.Vehicle with null record;
overriding -- optional
function Start(Self : Tractor) return string is
begin
return "Tractor starting!";
end Start;
type Car is new packageVehicle.Vehicle with null record;
overriding -- optional
function Start(Self : Car) return string is
begin
return "Car starting!";
end Start;
procedure TestVehicle(Vehicle : packageVehicle.Vehicle) is
begin
Ada.Text_IO.Put_Line( "Testing a vehicle" );
Ada.Text_IO.Put_Line( Start(Vehicle) );
end;
Tractor0 : Tractor;
Car0 : Car;
begin
Ada.Text_IO.Put_Line( TestVehicle(Tractor0) );
Ada.Text_IO.Put_Line( TestVehicle(Car0) );
end Main;
Compiler says:
Builder results warning: declaration of "TestVehicle" is too late
Builder results warning: spec should appear immediately after declaration of "Vehicle"
The key thing to be aware of is "All user-defined primitive subprograms of an interface type shall be abstract subprograms or null procedures." (Ref) I.e. you can't define a subprogram that takes the interface itself as a parameter (yes, I know this is different from Java.) This is why you're getting the error on the TestVehicles declaration.
Essentially, you have to define a type that implements the interface(s), then work with that type.
The Ada Rationale chapter on Interfaces discusses this in some detail.
Here's a working example based on your question--I renamed some things and fixed a couple errors that were probably getting lost amongst the error messages you were seeing :-) Note the addition of a type 'Concrete_Vehicles' that instantiates the Vehicle interface.
with Ada.Text_IO; use Ada.Text_IO;
procedure Interface_Test is
package Package_Vehicle is
type Vehicle is interface;
function Start(Self : Vehicle) return String is abstract;
end Package_Vehicle;
type Concrete_Vehicles is abstract new Package_Vehicle.Vehicle with null record;
type Tractor is new Concrete_Vehicles with null record;
overriding -- optional
function Start(Self : Tractor) return string is
begin
return "Tractor starting!";
end Start;
type Car is new Concrete_Vehicles with null record;
overriding -- optional
function Start(Self : Car) return string is
begin
return "Car starting!";
end Start;
procedure TestVehicle(Vehicle : Concrete_Vehicles'Class) is
begin
Ada.Text_IO.Put_Line( "Testing a vehicle" );
Ada.Text_IO.Put_Line( Start(Vehicle) );
end;
Tractor0 : Tractor;
Car0 : Car;
begin
TestVehicle(Tractor0);
TestVehicle(Car0);
end Interface_Test;
Compiling and running:
[22] Marc say: gnatmake interface_test.adb
gcc -c interface_test.adb
gnatbind -x interface_test.ali
gnatlink interface_test.ali
[23] Marc say: ./interface_test
Testing a vehicle
Tractor starting!
Testing a vehicle
Car starting!
Java-style interfaces was introduced in Ada2005:
type Vehicle is interface;
Any operations on the interface must be abstract:
function start(Self : Vehicle) return String is abstract;
When inheriting the interface, you must specify it as a parent, and implement the
operations defined for the interface ("overriding" tells the compiler that the parent must have a corresponding "start". The keyword is optional, however):
type Tractor is new Vehicle with null record;
overriding -- optional
function start(Self : Tractor) return String;
I will leave the rest as an exercise, you can read more about interfaces in the wikibook
Below is a working version of your program, using pointers (called "access" in Ada). You don't need an implementation of the interface to work with the interface, same as in your Java example, which is the main point of object oriented programming and polymorphism.
with Ada.Text_IO;
procedure Main is
package packageVehicle is
type Vehicle is interface;
function Start(Self : Vehicle) return String is abstract;
end packageVehicle;
type Tractor is new packageVehicle.Vehicle with null record;
overriding -- optional
function Start(Self : Tractor) return string is
begin
return "Tractor starting!";
end Start;
type Car is new packageVehicle.Vehicle with null record;
overriding -- optional
function Start(Self : Car) return string is
begin
return "Car starting!";
end Start;
procedure TestVehicle(Vehicle : Access packageVehicle.Vehicle'class) is
begin
Ada.Text_IO.Put_Line( "Testing a vehicle" );
Ada.Text_IO.Put_Line( Vehicle.Start );
end;
Tractor0 : access Tractor'Class := new Tractor;
Car0 : access Car'Class := new Car;
begin
TestVehicle(Tractor0);
TestVehicle(Car0);
end Main;
PS: I'm new to Ada, I might be wrong with things, but I have the idea from https://github.com/raph-amiard/ada-synth-lib where this concept is used a lot.
In Matlab, I would like to perform some operations on private members of a class. I would also like to perform this exact same task on other classes as well. The obvious solution is to write a function in a separate M file that all the classes call in order to perform this task. However, that seems impossible in Matlab (see below). Is there another way to accomplish this?
Here is the problem specifically: suppose I have one m file with the contents
classdef PrivateTest
properties (Access=private)
a
end
methods
function this = directWrite(this, v)
this.a = v;
end
function this = sameFileWrite(this, v)
this = writePrivate(this, v);
end
function this = otherFileWrite(this, v)
this = otherFileWritePrivate(this, v);
end
function print(this)
disp(this.a);
end
end
end
function this = writePrivate(this, v)
this.a = v;
end
...and another m file with the contents
function this = otherFileWritePrivate(this, v)
this.a = v;
end
After instantiating p = PrivateTest, both of these commands work fine (as expected):
p = p.directWrite(1);
p = p.sameFileWrite(2);
...but this command doesn't work even though it's the same code, just in a different m file:
p = p.otherFileWrite(3);
So, it seems like any code that performs operations on private properties of a class MUST be in the same m file as the classdef that defines those private properties. Another possibility might be to have all the classes inherit a class with the writing method, but Matlab doesn't allow this either. In one m file, I would have this code:
classdef WriteableA
methods
function this = inheritWrite(this, v)
this.a = v;
end
end
end
...and in another m file I would have this code:
classdef PrivateTestInherit < WriteableA
properties (Access=private)
a
end
end
However, after instantiating p = PrivateTestInherit;, the command p.inheritWrite(4) causes the same error message as before: "Setting the 'a' property of the 'PrivateTestInherit' class is not allowed."
In light of this, How is it possible to generalize code that manipulates private properties in Matlab, or is it possible?
It is not possible to manipulate private properties outside of the class, that is why they are called private. This idea is called encapsulation.
You can in solve it in many ways:
Define public property that wraps the private, and change it. (See code below)
(Inheritance pattern) Do a common father class, your other classes inherit the function
classdef PrivateTest
properties (Access=private)
a
end
properties(Access=public,Dependent)
A
end
methods
function this = set.A(this,val)
this.a = val;
end
function val = get.A(this)
val = this.a;
end
function this = directWrite(this, v)
this.a = v;
end
function this = sameFileWrite(this, v)
this = writePrivate(this, v);
end
function this = otherFileWrite(this, v)
this = otherFileWritePrivate(this, v);
end
function print(this)
disp(this.a);
end
end
end
function this = writePrivate(this, v)
this.A = v;
end