Lat initiering

Inom datorprogrammering är lat initialisering taktiken att fördröja skapandet av ett objekt , beräkningen av ett värde eller någon annan dyr process tills första gången det behövs. Det är en sorts lat utvärdering som specifikt hänvisar till instansieringen av objekt eller andra resurser.

Detta åstadkoms vanligtvis genom att utöka en accessormetod (eller egenskapsgetter) för att kontrollera om en privat medlem, som fungerar som en cache, redan har initierats. Om den har det, returneras den direkt. Om inte skapas en ny instans, placeras i medlemsvariabeln och returneras till den som ringer just-in-time för första användning.

Om objekt har egenskaper som sällan används kan detta förbättra starthastigheten. Genomsnittlig programprestanda kan vara något sämre när det gäller minne (för tillståndsvariablerna) och exekveringscykler (för att kontrollera dem), men effekten av objektinstansieringen sprids i tiden ("amortiseras") snarare än koncentreras till startfasen av ett system, och därmed kan mediansvarstiderna förbättras avsevärt.

I flertrådad kod måste åtkomst till latinitierade objekt/tillstånd synkroniseras för att skydda mot tävlingsförhållanden .

"Den lata fabriken"

I en mjukvarudesignmönstervy används ofta lat initialisering tillsammans med ett fabriksmetodmönster . Detta kombinerar tre idéer:

  • Använda en fabriksmetod för att skapa instanser av en klass ( fabriksmetodmönster )
  • Lagra instanserna i en karta och returnera samma instans till varje begäran om en instans med samma parametrar ( multitonmönster )
  • Använda lat initiering för att instansiera objektet första gången det efterfrågas (lat initieringsmönster)

Exempel

ActionScript 3

Följande är ett exempel på en klass med lat initialisering implementerad i ActionScript :

 

	   
	
		  
		      
	 
		  
		
			  
		
		
		    
		
			 
		
	 
		   
		
			    
		
	 
		   
		
			      
			
				
				
			
		
	 paketexempel  .  _  lazyinstantiation  {  public  class  Fruit  {  private  var  _typeName  :  String  ;  private  static  var  instancesByTypeName  :  Dictionary  =  new  Dictionary  ();  public  function  Fruit  (  typeName  :  String  )  :  void  {  this  .  _typeName  =  typName  ;  }  public  function  get  typeName  ()  :  String  {  return  _typeName  ;  }  public  static  function  getFruitByTypeName  (  typName  :  String  )  :  Fruit  {  return  instanserByTypeName  [  typName  ]  ||=  new  Fruit  (  typName  );  }  public  static  function  printCurrentTypes  ()  :  void  {  for  each  (  var  fruit  :  Fruit  in  instancesByTypeName  )  {  // itererar genom varje värdespår  (  fruit  .  typeName  )  ;  }  }  }  } 

Grundläggande användning:



	 
	
	   
	
		  
		
			
			
	 
			
			
	 
			
			
		
	
 paket  {  importexempel  .  _  latinstantiation  ;  public  class  Main  {  public  function  Main  ()  :  void  {  Fruit  .  getFruitByTypeName  (  "Banana"  );  Frukt  .  printCurrentTypes  ();  Frukt  .  getFruitByTypeName  (  "Apple"  );  Frukt  .  printCurrentTypes  ();  Frukt  .  getFruitByTypeName  (  "Banana"  );  Frukt  .  printCurrentTypes  ();  }  }  } 

C

I C skulle lat utvärdering normalt implementeras i en enda funktion, eller en enda källfil, med hjälp av statiska variabler .

I en funktion:

 
 
 
 

  
     
      
     
    


    
       
      
      
           
         0   
             
        
         
        
        
         
    
      
      
      
     




     
     
      
        
         
        
    
            
            
              
        
    
     0
 #include  <string.h>  #include  <stdlib.h>  #include  <stddef.h>  #include  <stdio.h>  struct  fruit  {  char  *  name  ;  struktur  frukt  *  nästa  ;  int  nummer  ;  /* Andra medlemmar */  };  struktur  frukt  *  get_frukt  (  char  *  namn  )  {  statisk  struktur  frukt  *  frukt_lista  ;  statisk  int  seq  ;  struktur  frukt  *  f  ;  for  (  f  =  fruktlista  ;  f  ;  f  =  f  ->  nästa  )  if  (  ==  strcmp  (  namn  ,  f  ->  namn  ))  returnera  f  ;  if  (  !  (  f  =  malloc  (  storleken på  (  strukturfrukt  )  )))  returnera  NULL  ;  if  (  !  (  f  ->  namn  =  strdup  (  namn  )))  {  gratis  (  f  );  returnera  NULL  ;  }  f  ->  tal  =  ++  följ  ;  f  ->  nästa  =  fruktlista  ;  fruktlista  =  f  ;  returnera  f  ;  }  /* Exempelkod */  int  main  (  int  argc  ,  char  *  argv  [])  {  int  i  ;  struktur  frukt  *  f  ;  if  (  argc  <  2  )  {  fprintf  (  stderr  ,  "Användning: frukt fruktnamn [...]  \n  "  );  utgång  (  1  );  }  for  (  i  =  1  ;  i  <  argc  ;  i  ++  )  {  if  ((  f  =  get_fruit  (  argv  [  i  ])))  {  printf  (  "Fruit %s: number %d  \n  "  ,  argv  [  i  ],  f  ->  nummer  );  }  }  returnera  ;  } 

Genom att använda en enda källfil i stället kan tillståndet delas mellan flera funktioner, samtidigt som det döljs från icke-relaterade funktioner.

fruit.h:




  
     
      
     
    


   
  

 #ifndef _FRUIT_INCLUDED_  #define _FRUIT_INCLUDED_  struct  fruit  {  char  *  name  ;  struktur  frukt  *  nästa  ;  int  nummer  ;  /* Andra medlemmar */  };  struktur  frukt  *  get_frukt  (  char  *  namn  );  void  print_fruit_list  (  FILE  *  fil  );  #endif  /* _FRUIT_INCLUDED_ */ 

frukt.c:

 
 
 
 
 

   
  

    
      
           
         0   
             
        
         
        
        
         
    
      
      
      
     


   
      
           
           
 #inkludera  <string.h>  #inkludera  <stdlib.h>  #inkludera  <stddef.h>  #inkludera  <stdio.h>  #inkludera  "fruit.h"  statisk  struktur  fruit  *  fruit_list  ;  statisk  int  seq  ;  struktur  frukt  *  get_frukt  (  char  *  namn  )  {  struktur  frukt  *  f  ;  for  (  f  =  fruktlista  ;  f  ;  f  =  f  ->  nästa  )  if  (  ==  strcmp  (  namn  ,  f  ->  namn  ))  returnera  f  ;  if  (  !  (  f  =  malloc  (  storleken på  (  strukturfrukt  )  )))  returnera  NULL  ;  if  (  !  (  f  ->  namn  =  strdup  (  namn  )))  {  gratis  (  f  );  returnera  NULL  ;  }  f  ->  tal  =  ++  följ  ;  f  ->  nästa  =  fruktlista  ;  fruktlista  =  f  ;  returnera  f  ;  }  void  print_fruit_list  (  FILE  *  file  )  {  struct  fruit  *  f  ;  för  (  f  =  fruktlista  ;  f  ;  f  =  f  ->  nästa  )  fprintf  (  fil  ,  "%4d %s  \n  "  ,  f  ->  nummer  ,  f  ->  namn  );  } 

main.c:

 
 
 

     
     
      
        
         
        
    
            
            
              
        
    
    
    
     0
 #include  <stdlib.h>  #include  <stdio.h>  #include  "fruit.h"  int  main  (  int  argc  ,  char  *  argv  [])  {  int  i  ;  struktur  frukt  *  f  ;  if  (  argc  <  2  )  {  fprintf  (  stderr  ,  "Användning: frukt fruktnamn [...]  \n  "  );  utgång  (  1  );  }  for  (  i  =  1  ;  i  <  argc  ;  i  ++  )  {  if  ((  f  =  get_fruit  (  argv  [  i  ])))  {  printf  (  "Fruit %s: number %d  \n  "  ,  argv  [  i  ],  f  ->  nummer  );  }  }  printf  (  "Följande frukter har genererats:  \n  "  );  print_fruit_list  (  stdout  );  återvända  ;  } 

C#

I .NET Framework 4.0 har Microsoft inkluderat en Lazy -klass som kan användas för att göra lazy loading. Nedan är en dummy-kod som gör lat inläsning av Class Fruit

    
    var  lazyFruit  =  new  Lazy  <  Fruit  >();  Frukt  frukt  =  lazyFruit  .  Värde  ; 

Här är ett dummy-exempel i C# .

Fruit gör ingenting här, klassvariabeln _typesDictionary är en Dictionary/Map som används för att lagra Fruit- instanser efter typName .

 
 
 

  

      
            

      
    
          
    

        
    
         

           
        
            
               

             
        
         
    

       
    
           0
        
             
            
                 
            
                
            
            
            
        
    
    
     
    
        
    


 

       
    
        
        

        
        

        
        
        
        

        
    
 använder  System  ;  använder  System.Collections  ;  använder  System.Collections.Generic  ;  public  class  Fruit  {  private  string  _typeName  ;  privat  statisk  ID-bok  <  string  ,  Fruit  >  _typesDictionary  =  ny  ordbok  <  sträng  ,  Fruit  >();  private  Fruit  (  String  typeName  )  {  this  .  _typeName  =  typName  ;  }  public  static  Fruit  GetFruitByTypeName  (  strängtyp  )  {  Fruit  fruit  ;  _  if  (!  _typesDictionary  .  TryGetValue  (  typ  ,  out  fruit  ))  {  // Lazy initialization  fruit  =  new  Fruit  (  typ  );  _typesOrdbok  .  Lägg till  (  typ  ,  frukt  );  }  returnera  frukt  ;  }  public  static  void  ShowAll  ()  {  if  (  _typesDictionary  .  Count  >  )  {  Console  .  WriteLine  (  "Antal gjorda instanser = {0}"  ,  _typesDictionary  .  Count  );  foreach  (  KeyValuePair  <  ​​string  ,  Fruit  >  kvp  i  _typesDictionary  )  {  Console  .  WriteLine  (  kvp  .  Key  );  }  Konsol  .  WriteLine  ();  }  }  public  Fruit  ()  {  // krävs så att provet kompileras  }  }  class  Program  {  static  void  Main  (  sträng  []  args  )  {  Fruit  .  GetFruitByTypeName  (  "Banana"  );  Frukt  .  Visa alla  ();  Frukt  .  GetFruitByTypeName  (  "Apple"  );  Frukt  .  Visa alla  ();  // returnerar redan existerande instans från första  // gången Fruit med "Banana" skapades  Fruit  .  GetFruitByTypeName  (  "Banana"  );  Frukt  .  Visa alla  ();  Konsol  .  ReadLine  ();  }  } 

Ett ganska okomplicerat "fyll-i-delarna"-exempel på ett designmönster för Lazy Initialization, förutom att detta använder en uppräkning för typen

 

  

    
    
        
          

    
    
      
    
        
        
        
        
        
    

    
      
    
          
          
    

    
       
    
           

         
        
             
                   
                
             
                   
                
             
                   
                
             
                   
                
             
                  
                
            
                  
                
        

         
    

    
    
         
    
            

            0      
        
              
        

         
    

     
    
        
    

       
    
        
         

        
           
        
               
              
              

             
        

         
    
 namnutrymme  DesignPatterns.LazyInitialization  ;  public  class  LazyFactoryObject  {  //intern samling av objekt  //IDictionary ser till att de är unika  privata  IDictionary  <  LazyObjectSize  ,  LazyObject  >  _LazyObjectList  =  ny  ordbok  <  LazyObjectSize  ,  LazyObject  >();  //enum för att skicka namn på storlek som krävs  //undviker att skicka strängar och är en del av LazyObject ahead  public  enum  LazyObjectSize  {  None  ,  Small  ,  Big  ,  Bigger  ,  Huge  }  //standardtyp av objekt som kommer att konstrueras  public  struct  LazyObject  {  public  LazyObjectSize  Storlek  ;  offentlig  IList  <  int  >  Resultat  ;  }  //tar storlek och skapa en 'dyr' lista  privat  IList  <  int  >  Resultat  (  LazyObjectSize  size  )  {  IList  <  int  >  result  =  null  ;  switch  (  storlek  )  {  case  LazyObjectSize  .  Small  :  result  =  CreateSomeExpensiveList  (  1,100  )  ;  _  bryta  ;  fall  LazyObjectSize  .  Big  :  result  =  CreateSomeExpensiveList  (  1  ,  1000  );  bryta  ;  fall  LazyObjectSize  .  Större  :  result  =  CreateSomeExpensiveList  (  1  ,  10000  );  bryta  ;  fall  LazyObjectSize  .  Huge  :  result  =  CreateSomeExpensiveList  (  1  ,  100000  );  bryta  ;  fall  LazyObjectSize  .  Ingen  :  resultat  =  null  ;  bryta  ;  default  :  result  =  null  ;  bryta  ;  }  returnera  resultat  ;  }  //inte ett dyrt objekt att skapa, men du får poängen  //fördröjer skapandet av något dyrt objekt tills det behövs  privat  IList  <  int  >  CreateSomeExpensiveList  (  int  start  ,  int  end  )  {  IList  <  int  >  result  =  new  List  <  int  > ();  for  (  int  räknare  =  ;  räknare  <  (  slut  -  start  );  räknare  ++)  {  resultat  .  Lägg till  (  start  +  räknare  );  }  returnera  resultat  ;  }  public  LazyFactoryObject  ()  {  //empty constructor  }  public  LazyObject  GetLazyFactoryObject  (  LazyObjectSize  size  )  {  //ja, jag vet att det är analfabet och felaktigt  LazyObject  noGoodSomeOne  ;  //hämtar LazyObjectSize från listan via ut, annars skapar en och lägger till den i listan  om  (!  _LazyObjectList  .  TryGetValue  (  size  ,  out  noGoodSomeOne  ))  {  noGoodSomeOne  =  new  LazyObject  ();  noGoodSomeOne  .  Storlek  =  storlek  ;  noGoodSomeOne  .  Resultat  =  detta  .  Resultat  (  storlek  );  _LazyObjectList  .  Lägg till  (  storlek  ,  noGoodSomeOne  );  }  returnera  noGoodSomeOne  ;  }  } 

C++

Här är ett exempel i C++ .

 
 
 

  
 
      
    

 
  
       

     

   



  



    
       
    
       
  
   



  
        
         
        
  
    


  
  
  

  
  

  
  
  
  














 #include  <iostream>  #include  <map>  #include  <string>  class  Fruit  {  public  :  static  Fruit  *  GetFruit  (  const  std  ::  string  &  type  );  statisk  tomrum  PrintCurrentTypes  ();  privat  :  // Notera: privat konstruktor tvingar en att använda statisk |GetFruit|.  Fruit  (  const  std  ::  sträng  &  typ  )  :  type_  (  typ  )  {}  statisk  std  ::  map  <  std  ::  sträng  ,  Fruit  *>  typer  ;  std  ::  strängtyp_  ;  _  };  // static  std  ::  map  <  std  ::  string  ,  Fruit  *>  Fruit  ::  types  ;  // Lazy Factory-metoden, får |Fruit| instans associerad med en viss   // |typ|. Skapar nya efter behov.   Fruit  *  Fruit::GetFruit  (  const  std  ::  sträng  &  typ  )  {  auto  [  it  ,  infogat  ]  =  typer  .  emplace  (  typ  ,  nullptr  );  if  (  insatt  )  {  it  ->  second  =  new  Fruit  (  typ  );  }  returnera  det  ->  sekund  ;  }  // Till exempel för att se mönster i aktion.  void  Fruit::PrintCurrentTypes  ()  {  std  ::  cout  <<  "Antal gjorda instanser = "  <<  typer  .  storlek  ()  <<  std  ::  endl  ;  for  (  const  auto  &  [  typ  ,  frukt  ]  :  typer  )  {  std  ::  cout  <<  typ  <<  std  ::  endl  ;  }  std  ::  cout  <<  std  ::  endl  ;  }  int  main  ()  {  Fruit  ::  GetFruit  (  "Banan"  );  Fruit  ::  PrintCurrentTypes  ();  Fruit  ::  GetFruit  (  "Apple"  );  Fruit  ::  PrintCurrentTypes  ();  // Returnerar redan existerande instans från första gången |Fruit| med "Banana"   skapades //.  Fruit  ::  GetFruit  (  "Banan"  );  Fruit  ::  PrintCurrentTypes  ();  }  // OUTPUT:  //  // Antal gjorda instanser = 1  // Banan  //  // Antal gjorda instanser = 2  // Äpple  // Banan  //  // Antal gjorda instanser = 2  // Äpple  // Banan  // 

Kristall

 
      
        

   
  

     
      
  

   
     
       
       
    
    
  

   
    
  









 klass  Frukt  privat  getter  typ  :  String  @@types  =  {}  av  String  =>  Frukt  def  initialize  (  @type  )  end  def  self  .  get_fruit_by_type  (  typ  :  String  )  @@types  [  typ  ]  ||=  Frukt  .  ny  (  typ  )  slut  def  själv  .  show_all  sätter  "Antal gjorda instanser:  #{  @@typer  .  storlek  }  "  @@typer  .  varje  gör  |  typ  ,  frukt  |  sätter  "  #{  typ  }  "  end  sätter  slut  def  self  .  storlek  @@typer  .  storlek  slutänd  Frukt  .  _  get_fruit_by_type  (  "Banan"  )  Frukt  .  show_all  Frukt  .  get_fruit_by_type  (  "Äpple"  )  Frukt  .  show_all  Frukt  .  get_fruit_by_type  (  "Banan"  )  Frukt  .  visa allt 

Produktion:

Antal gjorda instanser: 1 Banan Antal gjorda instanser: 2 Banana Apple Antal gjorda instanser: 2 Banana Apple

Haxe

Här är ett exempel i Haxe

  
         

     

     
      
  

      
      
        
    
     
  

      
       
  
 class  Fruit  {  private  static  var  _instances  =  new  Map  <  String  ,  Fruit  >();  public  var  name  (  default  ,  null  ):  String  ;  public  function  new  (  namn  :  String  )  {  this  .  namn  =  namn  ;  }  offentlig  statisk  funktion  getFruitByName  (  namn  :  String  ):  Fruit  {  if  (  !  _instances  .  exists  (  name  ))  {  _instances  .  set  (  namn  ,  ny  Frukt  (  namn  ));  }  returnerar  _instanser  .  (  namn  );  }  offentlig  statisk  funktion  printAllTypes  ()  {  spåra  ([  för  (  nyckel  in  _instanser  .  nycklar  ())  nyckel  ]);  }  } 

Användande

  
       
       
       
       
    
       
    
     
  
 class  Test  {  public  static  function  main  ()  {  var  banana  =  Fruit  .  getFruitByName  (  "Banana"  );  var  äpple  =  Frukt  .  getFruitByName  (  "Apple"  );  var  banan2  =  Frukt  .  getFruitByName  (  "Banana"  );  spår  (  banan  ==  banan2  );  // Sann. samma banan   Frukt  .  printAllTypes  ();  // ["Banan","Äppel"]  }  } 

Java

Här är ett exempel i Java .

 
 
 

   

    


         
        
        
        
        
        
        
    


  
    
    
    


  

           
    
    



       
    
    
    





         
         
                
                
                
          
            
               
             
          
            
              
        
        
         
    
    
    






         
          
              
                
                
                  
                    
                      
                
            
        
        
         
    
    
    


        
           0 
 
             
            
                  
                   
                  0  
                
            
            
            
        
    
 importera  java.util.HashMap  ;  importera  java.util.Map  ;  importera  java.util.Map.Entry  ;  public  class  Program  {  /**  * @param args  */  public  static  void  main  (  String  []  args  )  {  Fruit  .  getFruitByTypeName  (  FruitType  .  banana  );  Frukt  .  showAll  ();  Frukt  .  getFruitByTypeName  (  FruitType  .  apple  );  Frukt  .  showAll  ();  Frukt  .  getFruitByTypeName  (  FruitType  .  banana  );  Frukt  .  showAll  ();  }  }  enum  FruitType  {  none  ,  apple  ,  banana  ,  }  class  Fruit  {  private  static  Map  <  FruitType  ,  Fruit  >  types  =  new  HashMap  <>  ();  /**  * Att använda en privat konstruktör för att tvinga fram fabriksmetoden.  * @param typ  */  private  Fruit  (  FruitType  type  )  {  }  /**  * Lazy Factory-metoden, hämtar Fruit-instansen associerad med en viss  *-typ. Instantierar nya efter behov.   * @param typ Alla tillåtna frukttyper, t.ex. APPLE  * @return Fruit-instansen som är associerad med den typen.  */  public  static  Fruit  getFruitByTypeName  (  FruitType-  typ  )  {  Fruit  fruit  ;  // Detta har samtidighetsproblem. Här är inte läs-till-typerna synkroniserade,   // så types.put och types.containsKey kan anropas samtidigt.  // Bli inte förvånad om informationen är skadad.  if  (  !  typer  .  containsKey  (  typ  ))  {  // Lazy initialization  fruit  =  new  Fruit  (  typ  );  typer  .  sätta  (  typ  ,  frukt  );  }  else  {  // OK, den är tillgänglig för närvarande  frukt  =  typer  .  (  typ  );  }  returnera  frukt  ;  }  /**  * Lazy Factory-metoden, hämtar Fruit-instansen associerad med en viss  * typ. Instantierar nya efter behov.  Använder dubbelkontrollerat låsmönster   * för användning i mycket samtidiga miljöer.  * @param typ Alla tillåtna frukttyper, t.ex. APPLE  * @return Fruit-instansen som är associerad med den typen.  */  public  static  Fruit  getFruitByTypeNameHighConcurrentVersion  (  FruitType  type  )  {  if  (  !  typer  .  containsKey  (  typ  ))  {  synchronized  (  types  )  {  // Kontrollera igen, efter att ha skaffat låset för att se till att  // instansen inte skapades under tiden av en annan thread  if  (  !  typer  .  containsKey  (  typ  ))  {  // Lata  initialiseringstyper  .  put  (  typ  ,  ny  Frukt  (  typ  ));  }  }  }  returtyper  .  _  (  typ  );  }  /**  * Visar alla inmatade frukter.  */  public  static  void  showAll  ()  {  if  (  types  .  size  ()  >  )  {  System  .  ut  .  println  (  "Antal gjorda instanser = "  +  typer  .  storlek  ());  for  (  Entry  <  FruitType  ,  Fruit  >  entry  :  types  .  entrySet  ())  {  String  fruit  =  entry  .  getKey  ().  toString  ();  frukt  =  Karaktär  .  till versaler  (  frukt  .  charAt  (  ))  +  frukt  .  delsträng  (  1  );  System  .  ut  .  println  (  frukt  );  }  System  .  ut  .  println  ();  }  }  } 

Produktion

Antal gjorda instanser = 1 Banan Antal gjorda instanser = 2 Banana Apple Antal gjorda instanser = 2 Banana Apple

JavaScript

Här är ett exempel i JavaScript .

    
     
    

  
    
     
  

     
      
           
           
      
       
    
       
        
           
        
      
    
  

   








 var  Fruit  =  (  function  ()  {  var  types  =  {};  function  Fruit  ()  {};  // räkna egna egenskaper i objekt  funktion  count  (  obj  )  {  return  Object  .  keys  (  obj  ).  length  ;  }  var  _static  =  {  getFruit  :  funktion  (  typ  )  {  if  (  typ av  typer  [  typ  ]  ==  'odefinierad'  )  {  typer  [  typ  ]  =  ny  Frukt  ;  }  returnerar  typer  [  typ  ];  },  printCurrentTypes  :  function  ()  {  console  .  log  (  'Antal av gjorda instanser: '  +  count  (  types  ));  for  (  var  typ  in  types  )  {  console  .  log  (  type  );  }  }  };  return  _static  ;  })();  Frukt  .  getFruit  (  'Apple'  );  Frukt  .  printCurrentTypes  ();  Frukt  .  getFruit  (  'Banan'  );  Frukt  .  printCurrentTypes  ();  Frukt  .  getFruit  (  'Apple'  );  Frukt  .  printCurrentTypes  (); 

Produktion

Antal gjorda instanser: 1 Apple Antal gjorda instanser: 2 Apple Banana Antal gjorda instanser: 2 Apple Banana

PHP

Här är ett exempel på lat initiering i PHP 7.4:




 

      
         

       
    
          
    

        
    
        
          
               
        

         
    

        
    
             
            
             
        
         
    
























 <?php  header  (  'Content-Type: text/plain; charset=utf-8'  );  klass  Fruit  {  privat  sträng  $type  ;  privat  statisk  array  $typer  =  array  ();  privat  funktion  __construct  (  sträng  $type  )  {  $this  ->  type  =  $type  ;  }  public  static  function  getFruit  (  sträng  $type  )  {  // Lazy initialisering sker här  if  (  !  isset  (  self  ::  types  [  $type  ]))  {  self  ::  types  [  $type  ]  =  new  Fruit  (  $type  );  }  returnera  själv  ::  typer  [  $typ  ];  }  public  static  function  printCurrentTypes  ()  :  void  {  echo  'Antal gjorda instanser: '  .  räkna  (  själv  ::  typer  )  .  "  \n  "  ;  foreach  (  array_keys  (  self  ::  typer  )  som  $key  )  {  echo  "  $key\n  "  ;  }  echo  "  \n  "  ;  }  }  Fruit  ::  getFruit  (  'Apple'  );  Fruit  ::  printCurrentTypes  ();  Fruit  ::  getFruit  (  'Banan'  );  Fruit  ::  printCurrentTypes  ();  Fruit  ::  getFruit  (  'Apple'  );  Fruit  ::  printCurrentTypes  ();  /*  OUTPUT:  Antal gjorda instanser: 1  Apple  Antal gjorda instanser: 2  Apple  Banana  Antal gjorda instanser: 2  Apple  Banana  */ 

Pytonorm

Här är ett exempel i Python .

 
         
          
    
 
       
          
    
         
            
              
        
         

   
      
    
     klass  Fruit  :  def  __init__  (  själv  ,  objekt  :  str  )  ->  Ingen  :  själv  .  item  =  item  class  Fruits  :  def  __init__  (  self  )  ->  None  :  self  .  objekt  =  {}  def  get_fruit  (  själv  ,  objekt  :  str  )  ->  Frukt  :  om  objektet  inte finns  i  själv  .  föremål  :  själv  .  items  [  item  ]  =  Frukt  (  artikel  )  returnerar  själv  .  items  [  item  ]  if  __name__  ==  "__main__"  :  fruits  =  Frukt  ()  print  (  fruits  .  get_fruit  (  "Apple"  ))  print  (  fruits  .  get_fruit  (  "Lime"  )) 

Rubin

Här är ett exempel i Ruby , på att lattigt initiera en autentiseringstoken från en fjärrtjänst som Google. Sättet som @auth_token cachelagras på är också ett exempel på memoisering .

 
 
   
     
          
      
  

  


  
 
 
  kräver  'net/http'  klass  Blogger  def  auth_token  @auth_token  ||=  (  res  =  Net  ::  HTTP  .  post_form  (  uri  ,  params  ))  &&  get_token_from_http_response  (  res  )  end  # get_token_from_http_response, uri och params definieras senare i klassens  slut  b  =  Bloggare  .  nya  b  .  instance_variable_get  (  :@auth_token  )  # returnerar noll  b  .  auth_token  # returnerar token  b  .  instance_variable_get  (  :@auth_token  )  # returnerar token 

Scala

Scala har inbyggt stöd för lazy variabel initiering.

 
    
    
 
    
             scala  >  val  x  =  {  println  (  "Hej"  );  99  } 
 Hej  x  :  Int  =  99           scala  >  lazy  val  y  =  {  println  (  "Hej!!"  );  31  } 
 y  :  Int  =  <  lazy  >    scala  >  y 
 Hej  !!  res2  :  Int  =  31    scala  >  y 
 res3  :  Int  =  31 

Småprat

Här är ett exempel i Smalltalk på en typisk accessormetod för att returnera värdet på en variabel med hjälp av lat initialisering.

    
            höjd  ^  höjd  om Ingen:  [  höjd  :=  2,0  ]  . 

Alternativet "icke lata" är att använda en initialiseringsmetod som körs när objektet skapas och sedan använda en enklare accessormetod för att hämta värdet.

    
          

    
         initialisera  höjd  :=  2,0  höjd  ^  höjd 

Observera att lat initialisering också kan användas i icke -objektorienterade språk .

Teoretisk datavetenskap

Inom området teoretisk datavetenskap är lazy initiering (även kallad en lazy array ) en teknik för att designa datastrukturer som kan fungera med minne som inte behöver initieras. Antag specifikt att vi har tillgång till en tabell T med n oinitierade minnesceller (numrerade från 1 till n ), och vill tilldela m celler i denna array, t.ex. vill vi tilldela T [ k i ] := v i för par ( k 1 , v 1 ), ..., ( k m , v m ) där alla k i är olika. Den lata initieringstekniken tillåter oss att göra detta i bara O( m )-operationer, snarare än att spendera O( m + n )-operationer för att först initiera alla arrayceller. Tekniken är helt enkelt att allokera en tabell V som ki lagrar paren ( ki , v i ) i någon godtycklig ordning, och att skriva för varje i i cellen T [ ] positionen i V där nyckeln k i är lagrad, vilket lämnar de andra cellerna i T oinitialiserade. Detta kan användas för att hantera frågor på följande sätt: när vi slår upp cell T [ k ] för vissa k , kan vi kontrollera om k är i intervallet {1, ..., m }: om det inte är det, då T [ k ] är oinitierad. Annars kontrollerar vi V [ T [ k ]] och verifierar att den första komponenten i detta par är lika med k . Om den inte är det, T [ k ] oinitierad (och råkade bara av en slump falla inom intervallet {1, ..., m }). Annars vet vi att T [ k ] verkligen är en av de initierade cellerna, och motsvarande värde är den andra komponenten i paret.

Se även

externa länkar