Classes are another programming convention I will expect all of you to be quite familiar with. How to declare
classes, how to define them, public/private/protected scopes, methods, attributes, inheritence, polymorphism,
etc. We will be introducing some new implementation strategies to classes, which I'm going to focus on more
on this page. Let's start with a bare-bones examples, that we'll then add to later on:
public class Slacker
{
protected int alpha;
public Slacker() { alpha = 42; }
public virtual void print()
{
Console.WriteLine("alpha = {0}", alpha);
}
}
Not terribly fancy. Your programming projects leading up to this class likely should have included many
more methods, attributes, constructors, and destructors, but the example here can serve as a quick way to
represent those larger projects.
One thing of important note in C# relates to inheritance. We cannot derive new classes from more than one
single parent class here, but this does afford us one convenience: the use of
base.
base is the general way a derived class can refer to its parent class, which can
be helpful in order to refer to method implementations from the parent class that we'll want to utilize
within the child class as well. For example:
public class Slackest : Slacker // Slackest being derived from Slacker
{
public Slackest() : base() // Help initialize by calling the base class default constructor
{
omega = 1729;
}
public override void print()
{
base.print(); // This will print the value of "alpha"
Console.WriteLine("omega = {0}", omega);
}
private int omega;
}
The
override keyword here is necessary as part of the re-implementation of the
base classes' virtual method.
C# will introduce two new access modifiers, in addition to public, private, and protected: those are
internal and
protected internal.
internal limits access to only code within the current assembly.
protected internal limits access to code within the current assembly
and
derived classes in other assemblies. Some of the rules you have to follow when using access modifiers
in C#:
-
Classes and structs declared in a namespace (as opposed to nested within
another class), may be either public or internal.
-
Derived classes cannot be more accessible than their parent classes.
-
Members of both structs and classes are private by default.
-
namespaces, interface members, enumeration members, and user-defined operators
are always public. namespaces may contain non-public members, though.
C# introduces the idea of a
sealed class (example:
sealed
public class Example). Basically, these are classes that prohibit derivation.
string is a sealed class.
There also exists the idea of a
partial class, which is a... well, partial
definition of a class. For example, I might find it useful to define my very complex, complicated
classes in such a fashion:
// This part will be the basic, bare-bones definition to kick-start implementation
public class VerySmart
{
// declare/define constructors, print methods, properties, interfaces, etc.
}
// This will be where all of my AI development will take place
public partial class VerySmart
{
// declare/define all manner of machine learning mechanisms
}
// This will be where all of my scientific visualization code will be implemented
public partial class VerySmart
{
// declare/define my data crunchers, GUI's, options for visualization
}
This is an excellent "divide and conquer" approach to large scale projects, wherein multiple programmers
can work on/implement the various features or components of a highly complex class, separately, without
needing to actively pull down the most recent version published by their group members.
abstract is the keyword used to describe something as having an incomplete or
missing implementation, that
must be overriden. As opposed to
virtual
, which
may forgo being overriden. In the context of methods, it would be what you might
have referred to previously as
pure virtual methods, which have no implementation
themselves and exist only to provide a template for derived classes to then make implementations for. For
example:
public abstract bool art();
You may also define classes themselves as being
abstract. This will prevent
you from ever instantiating an object from this class, but can be used to define an even broader
template class by which other classes will be derived. An example of this might be concerning the
representation of an organization of specialized people. You could build an
abstract class called "Human", followed by derived classes called, "Customer", "Supervisor",
and, "
Tyrannical Overseer of Enrollment Undergraduate Advisor".
The modifier
static can be applied to classes, attributes, methods,
properties, operators, events, and constructors. Generally speaking, things that are qualified as
static are not instantiated more than once, nor are they directly associated
with instantiations. They simply exist, with your code referring to their singular definition
directly. For example:
public class Slacker
{
public static readonly float PI = 3.14159;
// Other stuff
}
To refer to PI, you wouldn't access it like an attribute of an object you've declared, like
alpha.PI but instead through the class itself:
Slacker.PI.
public static class Wrapper may be the closest we get to standalone
functions and code in C#, as you wouldn't create an object from this class in order to refer to
its attributes and methods but instead would also use
Wrapper.aGoodMethod(). Your utility or frequently used methods/definitions/variables
might find a good home within a static class that is shared among the various projects you work on.