morzel.net

.net, js, html, arduino, java... no rants or clickbaits.

Differences in Java and C#: protected

Java and C# are very similar languages so if you have to switch between the two it’s easy to overlook subtle differences. One of the tricky bits is the meaning of protected access modifier. 

In C#, if you mark a field with protected keyword it will be available to the class that owns it and to its derived classes. In Java access will be broader. Not only the owner and derived classes will be able to access the field but also all classes defined in the same package. In C# similar effect can be achieved by assigning protected internal access level. Member marked like that has access which is a union of internal (same assembly) and protected levels. Important thing to note is that concepts of Java package and C# assembly are not equivalent. C# assembly can span multiple namespaces and is related to physical unit (EXE, DLL) that keeps intermediate code and metadata. Package in Java is more similar to namespace in C# with key (not only) difference that it has an impact on accessibility…

Below are two projects that show protected access level differences between Java and C# (both are available in this GitHub repository). C# program was made in Visual Studio 2015 Community and targets .NET 4.5.2. Java program was made in IntelliJ IDEA 15 Community Edition and is set to use Java 8. Version of Java/.NET is not relevant and there’s nothing special in the projects - could’ve been easily done in notepad but isn’t it great that this days we can get such awesome IDEs for free? :) 

Java and C# projects... Click to enlarge...

Java

Base.java

package com.example;

public class Base {
    protected int someProtectedFiled = 123;

    public void testAccessInBaseClass() {
        // SAME BEHAVIOR IN JAVA AND C#
        // The class can access its own protected field
        System.out.println(someProtectedFiled);
    }
}

Derived.java

package com.example;

public class Derived extends Base {
    public void testAccessInDerivedClass() {
        // SAME BEHAVIOR IN JAVA AND C#
        // The class can access inherited protected field
        System.out.println(someProtectedFiled);

        // DIFFERENT BEHAVIOR IN JAVA AND C#!
        // Access to protected field is possible because classes are in the same package
        // (notice access through qualifier of type Base instead of Derived)
        System.out.println(new Base().someProtectedFiled);
        // In C# the field would have to be public or protected internal (otherwise CS1540 error is produced)
    }
}

NotDerived.java

package com.example;

public class NotDerived {
    public void testAccessInNotDerivedClass() {
        // DIFFERENT BEHAVIOR IN JAVA AND C#!
        // Access to protected field is possible because classes are in the same package
        System.out.println(new Base().someProtectedFiled);
        // In C# the field would have to be public or protected internal (otherwise CS0122 error is produced)
    }
}

DerivedInAnotherPackage.java

package com.example.another;

import com.example.Base;

public class DerivedInAnotherPackage extends Base {
    public void testAccessInDerivedClassFromAnotherPackage() {
        // SAME BEHAVIOR IN JAVA AND C#
        // The class can access inherited protected field even from another package
        System.out.println(someProtectedFiled);

        // SAME BEHAVIOR IN JAVA AND C#
        // For the below to work (instead of compilation error) the field would have to be public
        // (notice access through qualifier of type Base instead of DerivedInAnotherPackage):
        // System.out.println(new Base().someProtectedFiled);
    }
}

C#

Base.cs

namespace Protected
{
    public class Base
    {
        protected int someProtectedFiled = 123;

        public void TestAccessInBaseClass()
        {
            // SAME BEHAVIOR IN JAVA AND C#
            // The class can access its own protected field            
            System.Console.WriteLine(someProtectedFiled);
        }
    }
}

Derived.cs

namespace Protected
{
    public class Derived : Base
    {
        public void TestAccessInDerivedClass()
        {
            // SAME BEHAVIOR IN JAVA AND C#
            // The class can access inherited protected field           
            System.Console.WriteLine(someProtectedFiled);

            // DIFFERENT BEHAVIOR IN JAVA AND C#!
            // For the below to work (instead of CS1540 compilation error) the field would have to be public            
            // or protected internal (notice access through qualifier of type Base instead of Derived):
            // System.Console.WriteLine(new Base().someProtectedFiled);
        }
    }
}

NotDerived.cs

namespace Protected
{
    public class NotDerived
    {
        public void TestAccessInNotDerivedClass()
        {
            // DIFFERENT BEHAVIOR IN JAVA AND C#!
            // For the below to work (instead of CS0122 compilation error) the field would
            // have to be public or protected internal:
            // System.Console.WriteLine(new Base().someProtectedFiled);
        }
    }
}

DerivedInAnotherAssembly.cs

using Protected;

namespace AnotherAssembly // Namespace doesn't matter
{
    public class DerivedInAnotherAssembly: Base
    {
        public void TestAccessInDerivedClassFromAnotherAssembly()
        {
            // SAME BEHAVIOR IN JAVA AND C#
            // The class can access inherited protected field even from another assembly            
            System.Console.WriteLine(someProtectedFiled);

            // SAME BEHAVIOR IN JAVA AND C#
            // For the below to work (instead of CS1540 compilation error) the field would have to be public
            // (notice access through qualifier of type Base instead of DerivedInAnotherAssembly):
            // System.Console.WriteLine(new Base().someProtectedFiled);           
        }
    }
}

I hope that comments in the code make everything clear and this dry topic is exhausted... I've just orderd USB shield for my Arduino so if it works the next post will be about moving this thing with PlayStation controller :)

Update (2016-03-14):

Unfortunately I don’t have time to write the post mentioned above but the good news is that you definitely can use SparkFun USB Host Shield with USB Host Shield 2.0 library to steer servos with PS3 controller :) Here’s a short video of how it worked on my paintball turret. And here’s a clip of test circuit (hardware diagram).