{$mode objfpc} {$h+} {$modeswitch duplicatelocals}

uses
	SysUtils;

type
	IVegetable = interface;
	TVegetable = class;

	IVegetableGarden = interface
		procedure Plant(const v: IVegetable);
		procedure RollCall;
		function GetName: string;
		property name: string read GetName;
	end;

	TVegetableGarden = class(TInterfacedObject, IVegetableGarden)
		name: string;
		constructor Create(const name: string);
		destructor Destroy; override;
		procedure Plant(const v: IVegetable);
		procedure RollCall;
		function GetName: string;
	private
		vegetables: array of IVegetable;
	end;

	IVegetable = interface
		procedure RespondToRollCall;
		procedure SetGarden(const garden: TVegetableGarden);
	end;

	TVegetable = class(TInterfacedObject, IVegetable)
		garden: TVegetableGarden;
		name: string;
		weight: single;
		constructor Create(const name: string; const weight: single);
		destructor Destroy; override;
		procedure RespondToRollCall;
		procedure SetGarden(const garden: TVegetableGarden);
	end;

	constructor TVegetableGarden.Create(const name: string);
	begin
		inherited Create;
		self.name := name;
	end;

	destructor TVegetableGarden.Destroy;
	var
		i: SizeInt;
	begin
		writeln('Огород «', name, '» уничтожается.');
		for i := 0 to High(vegetables) do
			vegetables[i].SetGarden(nil);
		inherited Destroy;
	end;

	procedure TVegetableGarden.Plant(const v: IVegetable);
	begin
		SetLength(vegetables, length(vegetables) + 1);
		vegetables[High(vegetables)] := v;
		v.SetGarden(self);
	end;

	procedure TVegetableGarden.RollCall;
	var
		i: SizeInt;
	begin
		for i := 0 to High(vegetables) do
			vegetables[i].RespondToRollCall;
	end;

	function TVegetableGarden.GetName: string;
	begin
		result := name;
	end;

	constructor TVegetable.Create(const name: string; const weight: single);
	begin
		inherited Create;
		self.name := name;
		self.weight := weight;
	end;

	destructor TVegetable.Destroy;
	begin
		writeln('Овощ «', name, '» уничтожается.');
		inherited Destroy;
	end;

	procedure TVegetable.RespondToRollCall;
	begin
		writeln('<', garden.name, '>: ', name, ', вес ', FloatToStrF(weight, ffGeneral, 6, 0), ' кг');
	end;

	procedure TVegetable.SetGarden(const garden: TVegetableGarden);
	begin
		self.garden := garden;
	end;

	procedure Main;
	var
		garden: IVegetableGarden;
	begin
		garden := TVegetableGarden.Create('ОВОЩИ');
		garden.Plant(TVegetable.Create('картофель', 1.4));
		garden.Plant(TVegetable.Create('чеснок', 0.05));
		garden.Plant(TVegetable.Create('Рируру', 54));
		garden.Plant(TVegetable.Create('PoppyFanboy', 65));
		garden.RollCall;
	end;

begin
	Main;
end.