eersteam eersteam - 6 months ago 10
Java Question

How does encapsulation works in OOP

public interface IShoulders {
public void move();
}

public class Body {

public void createBody(){
RightHand rightHand = new RightHand();
rightHand.move();
IShoulders leftHand = new LeftHand();
leftHand.move();
}

}

public class RightHand implements IShoulders {

public void move(){
System.out.println("Move Right Hand");
}
}

public class LeftHand implements IShoulders {

public void move(){
System.out.println("Move Left Hand");
}
}
public class Main {

public static void main(String[] args){

Body myBody1 = new Body();
myBody1.createBody();


Body myBody2 = new Body();
myBody2.createBody();
}

}


Please explain in the class
body
how is the encapsulation different when
IShoulder leftHand = new LeftHand();
is used in comparison with
RightHand rightHand = new RightHand();
they are both doing the same thing so when to use what and why is it important ? thank you

Answer

What it comes down to is that when accessing a field, you access it as it is immediately typed. In this case, when you have a field typed as an interface: IShoulders, you can only directly access any properties/methods defined by the interface. When you access a field defined as a class that implements that same interface, this new field, defined and accessed as RightHand, provides access to not only those properties/methods defined by IShoulders but also and extended properties/methods defined by the class RightHand.

With your definitions, there is no real difference here aside from the value that move() prints out, but take the following changes:

public class RightHand implements IShoulders {

    public void move(){
        System.out.println("Move Right Hand");          
    }
    public void Gesture()
    {
        System.out.println("Make a gesture with Right Hand");
    }   
}

The new Gesture method is only accessible to a field defined as RightHand, it will not exist on a field that is defined only has IShoulders, even if you assign the field using a new RightHand(), you would need to box or convert the field to RightHand to access the new method.

Given the above RightHand class definition, try the following:

IShoulders shoulder = new RightHand();
shoulder.move(); // this will work fine...
shoulder.Gesture(); // this will not be possible as "Gesture()" does not exist on IShoulders.
((RightHand)shoulder).Gesture(); // this will work after casting shoulder as RightHand
                                 // since the underlying object is actually a RightHand.

Then try the following:

RightHand rhand = new RightHand();
rhand.move(); // again, this works fine...
rhand.Gesture(); // this now works fine too..

Further more, the interface is your contract for any class that implements it. It simply says that if a class implements an interface, it must implement everything in that interface. It says nothing, however, about HOW it should be implemented. So, as long as the class implements the structure of the interface, the contents of those implementations can be completely customized to each individual class.

The alternative to implementing an interface is creating a derived class using a sub-class. This can seem similar to implementing an interface, however the base class already has implementations of the properties and methods. They can be overridden unless you either do not decorate them with virtual or, at another level of inheritance, you override and use the final decoration.

I;m sorry but lets tone this down as its still a little confusing. When i write IShoulder rightHand or RightHand rightHand i;m defining the type of the object before creating it? Also i always wanted to ask why we need to define a type if we are using the new keyword anyway like we do with any other objects like of collections? list<> mylist = new list<> and how to address this verbally? like object rightHand of class RightHand encapsulate RightHand/IShoulder? correct me if iam wrong – eersteam

Sure, so as for typing variables - this allows for the compiler (and programmer, for that matter) to strongly define what can be used, and how it can be used in regards to an object/value. A simple example would be a function:

public string HyphenateTwoWords(string word1, string word2)
{
   return string.Format("{0}-{1}", word1, word2);
}

The above function takes two string parameters and joins them together with a hyphen between them. If the parameters were not typed as string, then anything could be passed in and the result could be simply wrong in some cases, or throw an exception in other cases. Since they are defined as string the string.Format() call executes without any issues.

Now, in C# and other languages, you can actually define a field/variable generically using var, for example:

List<string> myStringList = new List<string>();
myStringList.Add("Test1");
myStringList.Add("Test2");
myStringList.Add("Test3");
foreach(var item in myStringList)
   Console.WriteLine(item);

This lets the compiler infer what the actual type of item is based upon what is assigned to it. However, in most cases, you would not really want to use var. It is best to explicitly type your variables, if for no other reasons, readability. It is a lot easier to see what the type of a variable is, especially when you are working in code maintained by multiple developers. Plus, explicitly typing a variable ensures that is will be used as intended, otherwise a handlable exception is thrown or the compiler will throw an error or warning upon build of the solution.

Now, in regards to your comment above:

...how would i know if its left hand or right hand? and in my example hands are not shoulders but hands are suppose to be attached to the should because shoulder makes them capable of moving. So how would you implement this? – eersteam

Let's design some interfaces and classes to illustrate their uses, I will make some changes/additions to what you have already all of these should be fairly straight forward- Take a look at AddLegs() method on the Body class and look at the LeftLeg class too.

public class BodyConstructor
{
    public interface IBody
    {
        int Age { get; set; }
        string Species { get; set; }
        BodyPartGroup Head { get; set; }
        BodyPartGroup Thorax { get; set; }
        BodyPartGroup Abdomen { get; set; }
        BodyPartGroup Pelvis { get; set; }
    }

    public interface IBodyPartGroup
    {
        BodyPartGroupType Type { get; set; }
        List<IBodyPart> BodyParts { get; set; }
    }

    public interface IBodyPart
    {
        LateralDirection LateralOrientation { get; set; }
        string Name { get; set; }
        List<IBodyPart> SubParts { get; set; }
        void Move();
    }

    public enum BodyPartGroupType
    {
        Head = 1,
        Thorax = 2,
        Abdomen = 3,
        Pelvis = 4,
    }

    public enum LateralDirection
    {
        Central = 0,
        Right = 1,
        Left = 2,
    }



    public class Body : IBody
    {
        public Body()
        {
            Head = new BodyPartGroup(BodyPartGroupType.Head);
            Thorax = new BodyPartGroup(BodyPartGroupType.Thorax);
            Abdomen = new BodyPartGroup(BodyPartGroupType.Abdomen);
            Pelvis = new BodyPartGroup(BodyPartGroupType.Pelvis);
        }
        public Body(int age, string species)
            : this()
        {
            Age = age;
            Species = species;
        }
        public int Age { get; set; }
        public string Species { get; set; }
        public BodyPartGroup Head { get; set; }
        public BodyPartGroup Thorax { get; set; }
        public BodyPartGroup Abdomen { get; set; }
        public BodyPartGroup Pelvis { get; set; }

        public void AddLimbs()
        {
            AddArms();
            AddLegs();
        }

        public void AddArms()
        {
            // Individual segments for the left arm
            BodyPart leftShoulder = new BodyPart("Left Shoulder", LateralDirection.Left);
            BodyPart leftArm = new BodyPart("Left Arm", LateralDirection.Left);
            BodyPart leftHand = new BodyPart("Left Hand", LateralDirection.Left);
            leftArm.SubParts.Add(leftHand);
            leftShoulder.SubParts.Add(leftArm);
            // Individual segments for the right arm
            BodyPart rightShoulder = new BodyPart("Right Shoulder", LateralDirection.Right);
            BodyPart rightArm = new BodyPart("Right Arm", LateralDirection.Right);
            BodyPart rightHand = new BodyPart("Right Hand", LateralDirection.Right);
            rightArm.SubParts.Add(rightHand);
            rightShoulder.SubParts.Add(rightArm);

            // Add arms to thorax
            Thorax.BodyParts.Add(rightShoulder);
            Thorax.BodyParts.Add(leftShoulder);

        }

        public void AddLegs()
        {
            // Individual segments for the left leg
            BodyPart leftHip = new BodyPart("Left Hip", LateralDirection.Left);
            LeftLeg leftLeg = new LeftLeg(); // Here we use the LeftLeg class instead, which inherits BodyPart
            BodyPart leftFoot = new BodyPart("Left Foot", LateralDirection.Left);
            leftLeg.SubParts.Add(leftFoot);
            leftHip.SubParts.Add(leftLeg);

            //Individual segments for the right leg
            BodyPart rightHip = new BodyPart("Right Hip", LateralDirection.Right);
            BodyPart rightLeg = new BodyPart("Right Leg", LateralDirection.Right);
            BodyPart rightFoot = new BodyPart("Right Foot", LateralDirection.Right);
            rightLeg.SubParts.Add(rightFoot);
            rightHip.SubParts.Add(rightLeg);

            // Add legs to pelvis
            Pelvis.BodyParts.Add(leftHip);
            Pelvis.BodyParts.Add(rightHip);
        }
    }

    public class BodyPartGroup : IBodyPartGroup
    {
        public BodyPartGroup()
        {
            BodyParts = new List<IBodyPart>();
        }
        public BodyPartGroup(BodyPartGroupType type)
            : this()
        {
            this.Type = type;
        }
        public BodyPartGroupType Type { get; set; }
        public List<IBodyPart> BodyParts { get; set; }
    }

    public class BodyPart : IBodyPart
    {
        public BodyPart()
        {
            SubParts = new List<IBodyPart>();
        }
        public BodyPart(string name, LateralDirection orientation)
            : this()
        {
            Name = name;
            LateralOrientation = orientation;
        }
        // Location of body part: Left, Central, Right
        public LateralDirection LateralOrientation { get; set; }
        public string Name { get; set; }
        public List<IBodyPart> SubParts { get; set; }
        public virtual void Move()
        {
            // Common body part movement code.
        }
    }

    public class LeftLeg : BodyPart
    {
        public LeftLeg()
        {
            Name = "Left Leg";
            LateralOrientation = LateralDirection.Left;
        }
        public override void Move()
        {
            // Custom left leg move code

            base.Move(); // Call base BodyPart.Move();
        }
    }
}
Comments