Code

Coding, Programming & Algorithms, Tips, Tweaks & Hacks
Search

Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Property getters & setters

In traditional OOP, if we wanted to get or set an object's private member, we would need to write a public method to do the job.
The reason behind making a member data private and then accessing it through a public method is to avoid the implementing-user to access it directly.
There can be many reasons for prohibiting direct access to member data to the implementing-code.
For example, you may want a radius of a Circle to be within the range of 10 - 500.

C++: Traditional OOP
class Circle
 {
        private:
          int radius;

        public:
          Circle(int radius = 15)
           {
                  setRadius(radius);
           }

          void setRadius(int radius)
           {
                  if (radius < 10 || radius > 500)
                   {
                          this->radius = -1;
                          cout << "Radius must be within the range of 10 - 500" << endl;
                   }
                  else
                   this->radius = radius;
           }

          int getRadius()
           {
                  return this->radius;
           }
 }

void main()
 {
        Circle c = Circle();
        c.setRadius(25);
        cout << c.getRadius();
 }
C++

In languages like PHP & Python & PERL which have a weak type system, a further check of the data type may be necessary.
But for Python unfortunately even traditional getter & setter methods cannot be implemted because Python doesn't have a public or private. Everything is public by default - though a member can be made private by prefixing two underscores to it. But this is only for convention, it doesn't really serve its true purpose.

PHP 5 and C# .NET have a getter and setter method feature, making it look like we're accessing the data member directly.

PHP
<?php
class Circle
 {
        private $radius; # integer

        # Constructor
        public function __construct($radius = 15)
         {
                self::__set('radius', $radius);
         }

        # Setter
        public function __set($name, $value)
         {
                switch ($name)
                 {
                        case 'radius':

                          if (!is_numeric($value)) # is_int() for strong type checking
                           throw new Exception('Radius must be of a numeric type');

                          if ($value < 10 || $value > 500)
                           throw new Exception('Radius must be within the range of 10 - 500');

                          $this->radius = $value;

                        break;

                        default:
                          throw new Exception("Attempt to set a non-existing property: $name");
                        break;
                 }
         }

        # Getter
        public function __get($name)
         {
                if (in_array($name, array('radius')))
                 return $this->$name;

                switch ($name)
                 {
                        default:
                          throw new Exception("Attempt to get a non-existing property: $name");
                        break;
                 }
         }

 }

$c = new Circle();
$c->radius = 25;
echo $c->radius;
>
PHP 5.x
C#
using System;

public class Circle
 {
        private int __radius = 5;

        public Circle()
         {
         }

        public Circle(int radius)
         {
                this.radius = radius; // This will call the property defined below
         }

        public int radius // Property getter/setter name cannot be the same as the member variable name
         {
                get
                 {
                        return __radius;
                 }

                set
                 {
                        if (value < 10 || value > 500)
                         throw new Exception("Radius must be within the range of 10 - 500");

                        __radius = value;
                 }
         }
 }

public class main
 {
        public static void Main(string[] args)
         {
                Circle c = new Circle(); // Circle c = new Circle(5); will throw an Exception
                c.radius = 25;
                Console.WriteLine(c.radius);
         }
 }
.NET 2.0

C# .NET 3.0 has introduced Automatic Properties where you don't need to specify code for the getter & setter - the compiler takes generates the method body.

JavaScript does seem to have a getter and setter method which I came across just now when searching for the official source to Java 7's new features' documentation, but :

  • only within an object initializer - not inside a function so it doesn't seem to be of much use as we can't create instances
  • doesn't hide the member from being accessed directly
  • doesn't work in IE.

JavaScript
var someObj =
 {
        a : 7,
        get b()
         {
                return this.a * 3;
         },
        set c(x)
         {
                this.a = x / 2;
         }
 }

someObj.foo1 = function()
 {
        //
 }

alert(someObj.a); // 7
alert(someObj.b); // 21
someObj.c = 5; alert(someObj.a); // 2.5
someObj.foo1();
JavaScript 1.5

The Getter & Setter feature does not seem to be a much "wanted" feature in the Java community.
Still, this has been proposed by Rémi Forax for JDK 7.

Java: Proposal
public class Circle
 {
        private int __radius = 5;

        public Circle()
         {
         }

        public Circle(int radius)
         {
                this.radius = radius; // This will call the property defined below
         }

        public property int radius // Property getter/setter name cannot be the same as the member variable name
         {
                get
                 {
                        return __radius;
                 }

                set (int radius)
                 {
                        if (radius < 10 || radius > 500)
                         throw new Exception("Radius must be within the range of 10 - 500");

                        __radius = radius;
                        // firePropertyChange(radius);
                 }
         }

        public static void main(String[] args)
         {
                Circle c = new Circle(2); // Circle c = new Circle(5); will throw an Exception
                c.radius = 25;
                System.out.println(c.radius);
         }
 }
JDK 7
Vanakkam !

Generating a Random String

PHP
<?php
class RandomText
 {
        const RAND_NUMBERS       = 1;
        const RAND_SMALL_LETTERS = 2;
        const RAND_CAP_LETTERS   = 4;
        const RAND_ALL           = 7;

        /**
         * @access public
         * @param Type (INT) One of the random constants RAND_*
         * @NoOfChars [INT] Optional - No of characters to generate
         * @return (string) random string
         * @example echo RandomText::Random_String(RandomText::RAND_NUMBERS + RandomText::RAND_CAP_LETTERS, 25);
         */
 	public static function Random_String($Type = self::RAND_NUMBERS, $NoOfChars = 6)
 	 {
 	 	$strList = array();

 	 	// Convert to binary format and find out what combination of random characters are required
 	 	$binType = base_convert($Type, 10, 2);

 	 	// Loop through the bits from Right To Left
 	 	for ($i = strlen($binType) - 1; $i >= 0; $i--)
 	 	 {
 	 	 	if ($binType[$i])
 	 	 	 {
 	 	 	 	switch (pow(2, strlen($binType) - $i - 1))
 	 	 	 	 {
 	 	 	 	 	default:

 	 	 	 	 	case self::RAND_NUMBERS:
 	 	 	 	 	 $Ascii_Range = array(48, 57);  // Numbers - Characters 0 to 9
 	 	 	 	 	break;

 	 	 	 	 	case self::RAND_SMALL_LETTERS:
   	 	 	 	 	 $Ascii_Range = array(97, 122); // Small Letters - Characters a to z
 	 	 	 	 	break;

 	 	 	 	 	case self::RAND_CAP_LETTERS:
 	 	 	 	 	 $Ascii_Range = array(65, 90);  // Capital Letters - Characters A to Z
 	 	 	 	 	break;
 	 	 	 	 }

 	 	 	 	for ($j = $Ascii_Range[0]; $j <= $Ascii_Range[1]; $j++)
 	 	 	 	 $strList[] = chr($j);
 	 	 	 }
 	 	 }

 	 	$RndString = "";
 	 	for ($i = 0; $i < $NoOfChars; $i++)
 	 	 $RndString .= $strList[rand(0, count($strList) - 1)];

 	 	return $RndString;
 	 }
 }

echo RandomText::Random_String(RandomText::RAND_NUMBERS + RandomText::RAND_CAP_LETTERS, 25);
?>
PHP 5.2.3
C#
using System;
using System.Text;

public class RandomText
 {
        public const int RAND_NUMBERS       = 1;
        public const int RAND_SMALL_LETTERS = 2;
        public const int RAND_CAP_LETTERS   = 4;
        public const int RAND_ALL           = 7;

        public static string Random_String()
         {
                return Random_String(RAND_NUMBERS, 6);
         }

        public static string Random_String(int Type)
         {
                return Random_String(Type, 6);
         }

        public static string Random_String(int Type, int NoOfChars)
         {
                StringBuilder strList = new StringBuilder();
                int[] Ascii_Range;
                int i;

                // Convert to binary format and find out what combination of random characters are required
                string binType = Convert.ToString(Type, 2);

                // Loop through the bits from Right To Left
                for (i = binType.Length - 1; i >= 0; i--)
                 {
                        if (binType[i] == '1')
                         {
                                switch ((int)Math.Pow(2, binType.Length - i - 1))
                                 {
                                        default:

                                        case RAND_NUMBERS:
                                         Ascii_Range = new int[] {48, 57};  // Numbers - Characters 0 to 9
                                        break;

                                        case RAND_SMALL_LETTERS:
                                         Ascii_Range = new int[] {97, 122};  // Small Letters - Characters a to z
                                        break;

                                        case RAND_CAP_LETTERS:
                                         Ascii_Range = new int[] {65, 90};  // Capital Letters - Characters A to Z
                                        break;
                                 }

                                for (int j = Ascii_Range[0]; j <= Ascii_Range[1]; j++)
                                 strList.Append((char)j);
                         }
                 }

 	 	StringBuilder RndString = new StringBuilder();
 	 	Random rnd = new Random();
 	 	
 	 	for (i = 0; i < NoOfChars; i++)
 	 	 RndString.Append(strList[rnd.Next(strList.Length - 1)]);

 	 	return RndString;
         }

        public static void Main(string[] args)
         {
                Console.WriteLine(RandomText.Random_String(RandomText.RAND_NUMBERS + RandomText.RAND_CAP_LETTERS, 25));
         }
 }
.NET 2.0
Java
import java.io.*;
import java.util.Random;

public class RandomText
 {
        public static final int RAND_NUMBERS       = 1;
        public static final int RAND_SMALL_LETTERS = 2;
        public static final int RAND_CAP_LETTERS   = 4;
        public static final int RAND_ALL           = 7;

        public static String Random_String()
         {
                return Random_String(RAND_NUMBERS, 6);
         }

        public static String Random_String(int Type)
         {
                return Random_String(Type, 6);
         }

        public static String Random_String(int Type, int NoOfChars)
         {
                StringBuilder strList = new StringBuilder();
                int[] Ascii_Range;
                int i;

                // Convert to binary format and find out what combination of random characters are required
                String binType = Integer.toString(Type, 2); // Type.toString(2);

                // Loop through the bits from Right To Left
                for (i = binType.length() - 1; i >= 0; i--)
                 {
                        if (binType.charAt(i) == '1')
                         {
                                switch ((int)Math.pow(2, binType.length() - i - 1))
                                 {
                                        default:

                                        case RAND_NUMBERS:
                                         Ascii_Range = new int[] {48, 57};  // Numbers - Characters 0 to 9
                                        break;

                                        case RAND_SMALL_LETTERS:
                                         Ascii_Range = new int[] {97, 122};  // Small Letters - Characters a to z
                                        break;

                                        case RAND_CAP_LETTERS:
                                         Ascii_Range = new int[] {65, 90};  // Capital Letters - Characters A to Z
                                        break;
                                 }

                                for (int j = Ascii_Range[0]; j <= Ascii_Range[1]; j++)
                                 strList.append((char)j);
                         }
                 }

                StringBuilder RndString = new StringBuilder();
                Random rnd = new Random();

                for (i = 0; i < NoOfChars; i++)
                 RndString.append(strList.charAt(rnd.nextInt(strList.length() - 1)));

                return RndString.toString();
         }

        public static void main(String[] args) throws Exception
         {
                System.out.println(RandomText.Random_String(RandomText.RAND_NUMBERS + RandomText.RAND_CAP_LETTERS, 25));
         }
 }
JDK 6.0
JavaScript
function RandomText()
 {
        this.RAND_NUMBERS       = 1;
        this.RAND_SMALL_LETTERS = 2;
        this.RAND_CAP_LETTERS   = 4;
        this.RAND_ALL           = 7;

        this.Random_String = function(Type, NoOfChars)
         {
                var strList = "";
                var Ascii_Range;
                var i;

                // Convert to binary format and find out what combination of random characters are required
                binType = Type.toString(2);

                // Loop through the bits from Right To Left
                for (i = binType.length - 1; i >= 0; i--)
                 {
                        if (binType[i] == '1')
                         {
                                switch (Math.pow(2, binType.length - i - 1))
                                 {
                                        default:

                                        case this.RAND_NUMBERS:
                                         Ascii_Range = new Array(48, 57);  // Numbers - Characters 0 to 9
                                        break;

                                        case this.RAND_SMALL_LETTERS:
                                         Ascii_Range = new Array(97, 122); // Small Letters - Characters a to z
                                        break;

                                        case this.RAND_CAP_LETTERS:
                                         Ascii_Range = new Array(65, 90);  // Capital Letters - Characters A to Z
                                        break;
                                 }

                                for (var j = Ascii_Range[0]; j <= Ascii_Range[1]; j++)
                                 strList += String.fromCharCode(j);
                         }
                 }

                var RndString = "";
                for (i = 0; i < NoOfChars; i++)
                 RndString += strList[Math.floor(Math.random() * strList.length)];

                return RndString;
         }
 }

var oRandomText = new RandomText();
alert(oRandomText.Random_String(oRandomText.RAND_NUMBERS + oRandomText.RAND_CAP_LETTERS, 25));
JavaScript 1.5
Python
import array
import random

def int2bin(n):
    "Convert an integer to binary - no built-in function"
    bStr = ''
    while n > 0:
          bStr = str(n % 2) + bStr
          n = n >> 1
    return bStr

class RandomText:

      RAND_NUMBERS       = 1;
      RAND_SMALL_LETTERS = 2;
      RAND_CAP_LETTERS   = 4;
      RAND_ALL           = 7;

      def Random_String(Type = RAND_NUMBERS, NoOfChars = 6):
          strList = array.array('c', '')

          # Convert to binary format and find out what combination of random characters are required
          binType = int2bin(Type)

          # Loop through the bits from Right To Left
          for i in range(len(binType) - 1, -1, -1):

              if binType[i] == '1':

                 x = 2 ** (len(binType) - i - 1)

                 if x == RandomText.RAND_NUMBERS:
                    Ascii_Range = [48, 57]   # Numbers - Characters 0 to 9
                 elif x == RandomText.RAND_SMALL_LETTERS:
                    Ascii_Range = [97, 122]  # Small Letters - Characters a to z
                 elif x == RandomText.RAND_CAP_LETTERS:
                    Ascii_Range = [65, 90]   # Capital Letters - Characters A to Z
                 else:
                    Ascii_Range = [48, 57]   # Numbers - Characters 0 to 9

                 for j in range(Ascii_Range[0], Ascii_Range[1] + 1):
                    strList.append(chr(j))

              RndString = array.array('c', '')

              for i in range(0, NoOfChars):
                  RndString.append(strList[random.randint(0, len(strList) - 1)])

          return RndString.tostring()

      Random_String = staticmethod(Random_String)


print RandomText.Random_String(RandomText.RAND_NUMBERS + RandomText.RAND_CAP_LETTERS, 25)
Python 2.5
Vanakkam !

All Possible Permutations

All possible permutations of a string - Total number of permutations of a given word taking all n letters is n!.
For example, the word post will give 24 possible permutations inclusive of the original word (post).

  1. post
  2. pots
  3. psot
  4. psto
  5. ptos
  6. ptso
  7. opts
  8. opst
  9. ostp
  10. ospt
  11. otsp
  12. otps
  13. spot
  14. spto
  15. sopt
  16. sotp
  17. stpo
  18. stop
  19. tpso
  20. tpos
  21. tosp
  22. tops
  23. tsop
  24. tspo

This snippet here doesn't exactly output permutations of a string, but its indexes - which should correspond to the array indexes.

C++
// All possible permutations upto n digits

#include<fstream.h>
#include<conio.h>

unsigned long fact(unsigned long);
void swap(int[], int, int);
void display(int[]);
void Add(int[], int);

ofstream fout("out.txt");

void main()
 {
        int j, k, n;
        unsigned long i;

        cout << "How many digits ? "; cin >> n;

        int *key = new int[n + 1];
        key[0] = n; // n contains the total no: of digits

        for (i = 1; i <=key[0]; i++)
         key[i] = i;

        display(key);
        swap(key, key[0], key[0] - 1);
        display(key);

        for (i = 3; i <= fact(key[0]); i+=2)
         {
                for (j = key[0] - 1; j >= 0; j--)
                 {
                        if ((i-1) % fact(j) == 0)
                         {
                                Add(key, key[0] - j);
                                for (k = 1; k <= key[0] - j - 1; k++)
                                 {
                                        if (key[k] == key[key[0] - j])
                                         {
                                                Add(key, key[0] - j);
                                                k = 0;
                                         }
                                 }
                         }
                 }

                display(key);
                swap(key, key[0], key[0] - 1);
                display(key);
         }

        cout << "Total no: of permutations = " << key[0] << "! = " << i - 1;
        fout.close();
 }

unsigned long fact(unsigned long f) { return f == 0 ? 1: f * fact(f - 1); }

void swap(int k[], int a, int b)
 {
        int t = k[a]; 
        k[a] = k[b];
        k[b] = t; 
 }

void display(int k[])
 {
        for(int i = 1; i <= k[0]; i++)
         fout << k[i];

        fout << '\n';
 }

void Add(int k[], int i)
 {
        k[i]++;
        if (k[i] == k[0] + 1)
         k[i] = 1;
 }

Now, its pretty obvious why I had the permutations written to a file instead of console output. 9! is 362,880 but 10! is 10 times 9! which is more than 3.5 million lines of text.

Update : I have ported the C code in Java with some modifications in the way output is handled. This is much safer than that big for loop.

Java
/*
javac Permutations.java
java Permutations post
*/
public class Permutations
{
        private int[] key;
        private String word, pWord;
        private int n, i = 1;

        public Permutations(String word)
        {
                this.word = word;

                n = word.length();
                key = new int[n + 1];

                for (int i = 1; i <= n; i++)
                 key[i] = i;
        }

        public boolean next()
        {
                if (i == 1)
                {
                        build();
                }
                else if (i == fact(n) + 1)
                {
                        return false;
                }
                else if (i % 2 == 0)
                {
                        swap(n, n - 1);
                        build();
                }
                else if (i % 2 == 1)
                {
                        int j, k;

                        for (j = n - 1; j >= 0; j--)
                        {
                                if ((i - 1) % fact(j) == 0)
                                {
                                        add(n - j);
                                        for (k = 1; k <= n - j - 1; k++)
                                        {
                                                if (key[k] == key[n - j])
                                                {
                                                        add(n - j);
                                                        k = 0;
                                                }
                                        }
                                }
                        }

                        build();
                }

                i++;
                return true;
        }

        private long fact(long f) { return f == 0 ? 1: f * fact(f - 1); }

        private void swap(int a, int b)
        {
                int t = key[a];
                key[a] = key[b];
                key[b] = t;
        }

        private void build()
        {
                StringBuilder s = new StringBuilder();

                for(int i = 1; i <= n; i++)
                 s.append(word.charAt(key[i] - 1));

                pWord = s.toString();
        }

        private void add(int i)
        {
                key[i]++;
                if (key[i] == n + 1)
                 key[i] = 1;
        }

        public String nextWord()
        {
                return pWord;
        }

        public static void main(String[] args)
        {
                if (args.length == 0)
                {
                        System.out.println("Got to give an argument");
                        System.exit(0);
                }

                Permutations p = new Permutations(args[0]);
                while (p.next())
                {
                        System.out.println(p.nextWord());
                }
        }
}
JDK 1.6

PS: I wrote this half a decade ago but never documented it. I'll try to update it with an explanation soon.

Vanakkam !