Shamelessly stolen from Janin's awesome OPs (all examples below written in Python):
Turning progamers into programmers hell yeah
I wrote up this wall of text while playing EVE. I hope that this thread will become a place where people new to programming can learn what languages are available, how to operate basic parts of programming, get help deciphering inscrutable homework assignments, etc. It might also serve as a useful repository for commonly-asked questions like "what is a pointer", "how do I write a function", etc.
Basic overview
In the code samples here, lines starting with the "#" character are comments. This means that they are not part of the program itself, but are instructions or notes to the reader.
Stuff that doesn't go anywhere specific
Always turn on compiler or interpreter warnings, and set them to maximum. If possible, make them errors rather than warnings. Compiler writers are very smart, and probably know more than you do. Read the documentation to your compiler or interpreter to determine how to set warning and error levels.
VariablesVariables are a way to "label" a certain value. They can be used to reduce code duplication. If you wanted to change the base value in the old code, you would have to update it in three places. In the new code, it only has to be updated in one.
# Old code
value1 = (5 * 10) + 5
value2 = (5 * 10) + 6
value3 = (5 * 10) + 7
# New code
base = 5 * 10
value1 = base + 5
value1 = base + 6
value1 = base + 7
To document code behavior. In the old code, the numbers "5", "10", and "100" are "magic numbers". Their purpose is unknown - may be it's how many cars have been sold, how many employees took the day off sick, or how many dollars were spent on candy bars. May be there's a comment hidden somewhere about its purpose, or may be not. In the new code, their purposes are inherently documented everywhere the variables are used.
# Old code
var = 100
income_today = var * 10 * 0.3
# New code
cent_multiplier = 100
net_dollar_income = 10
tax_rate = 0.3
income_today = net_dollar_income * cent_multiplier * tax_rate
In most modern languages, variables have "types". A type determines what values a variable can hold and what operations you can perform on it. For example, you can add two numbers, but cannot add a number and a string.
Common types of variables:
Boolean - May be either True or False, nothing else. In some primitive languages, such as C, the integers 0 and 1 are used instead of true and false.
Integer - A number with no fractional part.
Floating Point - A number that may contain fractional parts. Because computers only operate on Base 2 numbers, floating point math in most languages can give very "weird" values. For an example, enter "javascript:alert (0.1 + 0.2)" into your browser's URL bar.
String - An ordered list of characters. These might be letters like A, digits like 2, punctuation like !, or "unprintable" control characters such as a "new line" marker.
List - An ordered list of variables. These are usually accessed by a "0-based" index. For example, position 0 of the list (5 10 15 20) is 5, and position 3 is 20.
ConditionalsConditionals are what separate a programming language from a mere list of equations. A conditional always has an if-block, and sometimes an else-block. In some languages, the two can be combined to save space. One thing to note here is the use of "==" to check for equality. Because "=" is used to assign to a variable, "==" checks if two values are equal.
An example of an if statement:
name = "Alice"
if name == "Alice":
print "Hello Alice!"
else:
if name == "Bob":
print "Guten Tag Bob!"
else:
print "I don't know who you are."
# The same as above, with a combined 'elif' statement
name = "Alice"
if name == "Alice":
print "Hello Alice!"
elif name == "Bob":
print "Guten Tag Bob!"
else:
print "I don't know who you are."
LoopsLoops are used to help reduce code duplication. If you have to do something many times, it's easier to put into a loop than try to write out every step. And if you want to change how many times something happens, it'll have to be in a loop.
The most basic form of the loop is the while loop. This loop will simply run over and over until some condition is met. If you make a mistake in the body, the loop might run forever and freeze your program.
x = 10
while x < 500:
x = x * 10
print x
The other popular form of the loop is the for loop. A for loop is used for doing something once for every item in a group.
numbers = [5, 10, 15, 20, 25, 30]
# The number is: 5
# The number is: 10
# etc
for number in numbers:
print "The number is: ", number
# The name is: Alice
# The name is: Bob
# etc
for name in ["Alice", "Bob", "Charlie", "David", "Eve"]:
print "The name is: ", name
Posts
Functions are another tool for reducing duplicated code (see the pattern yet?). Just like a function in mathematics, a programming function takes some variables as input and returns some as output. Unlike mathematical functions, programming functions can do other things as well, such as save files or send stuff to the user. A function will run until it reaches a "return" statement, at which point it will give control of the program back to the parent function.
Basic functions
I'll define a simple function here, so you can see how it's put together. As an example I will use the Fibonacci function, which is defined thus:
Keyword parameters
Some languages support a concept known as "keyword parameters", which makes it easier to remember what goes where if the function has many parameters. An example using the income_today example from earlier:
Functions as parameters
As one last functional feature, some languages support functions as parameters! These are fun. I'll use an example of searching a list for a value that matches the passed in function. This code sample will check if a list of names contains "Alice" or "Bob".
Languages are broadly split into two categories, dynamic and static. A static language has types fixed when it's run. If a function in a static language expects to get an integer, you can't pass it a float instead. For this guide, I will be focusing on dynamic languages, because I find them easier to read, write, and maintain. Specifically, I will cover Python (my personal favorite), with a small detour into Javascript.
Dynamic languages
An incomplete list of popular dynamic languages:
Python - Popular for everything from game scripting (Battlefield 2, Civilization 4) to web applications to physics simulations. My personal favorite.
Ruby - A less well-known language than Python, Ruby has seen a resurgence with the advent of Rails, a popular web application development framework.
Lisp - A somewhat popular language following the "functional" paradigm, the basis for programs such as GNU Emacs and...uh...
Smalltalk - Still one of the best object-oriented languages around. Many of the ideas in Smalltalk were used in Objective C, which forms the basis for much of OS X.
Perl - Very popular for UNIX scripting, but is infamous for being rather easy to make incomprehensible.
ECMAScript/Javascript - The most popular and widely installed language on the planet. Has gained a reputation as a horribly awful language due to incompetant monkeys writing in it, but in reality it's only moderatly awful.
Python
One of the most popular dynamic languages, used for everything from large websites like Google to game scripting. All data is modeled as "dictionaries" -- otherwise known as "associative arrays" or "hash tables" in other languages. Objects, modules, and full libraries are simply dictionaries of attributes. Python is also a philosophy -- well-written code is said to be "Pythonic" if it obeys the Python philosophy, which emphasizes explicit behavior and "one obvious way to do it". Python is said to be "batteries included", and features a massive standard library.
Ruby
Borrows the good ideas from Perl, Smalltalk, and Lisp. All data is contained in objects, and all objects communicate by passing around "messages". Message passing is the distinguishing characteristic of Ruby and Smalltalk. It allows very flexible programming by making a class responsible for *all* of its behavior. Want to set the "bar" attribute of object "foo"? When you execute "foo.bar = 1", you're actually performing "foo.bar= (1)". No modifications to an objects state are permitted except through its messages.
ECMAScript/Javascript
Crazy shit, "some text" + 10 = "some text10" instead of an error. Use a library like jQuery or you will go mad.
Static languages
Rather than try to describe all the differences between dynamic and static languages all at once, here's an example of printing out names from earlier. Keep in mind that both versions are the full program (C++ example):
There are several things to notice here:
- The definition of the main() function. A static language such as C requires that all code be placed in functions. In practice you will rarely write code outside of a function in any language, but it can be helpful for learning how to program.
- The code uses an array, rather than a list. The nuances of arrays are discussed in a following post.
- The for loop is dramatically different. Rather than simply passing each value into the block, the user must manually construct, check, and update an index variable.
- The print function requires that the user specify what is being printed (a string, "%s"). If you specify an incorrect type code, the program is likely to crash.
For this reason, I do not advise new programmers to immediately jump into using languages such as C/C++/C#/Java. When you've learned how to walk, then you can learn how to walk in lead boots. I especially ask that you do not start with any dialect of Basic, because the available good example code is dwarfed by the amount of bug-riddled, insecure garbage.
EDIT: I've added some more to this, but I'm really lazy and OOP is a big subject.
Object-oriented Programming
The two core principles of object-oriented design are information hiding and behavior sharing. Rather than a mass of single-purpose functions, bundle them together to provide a clean interface for the rest of the code to access.
Information hiding
Just as a function protects other code from having to know what operations it goes through to arrive at a conclusion, OOP protects other code from knowing what function is being called and what data is being used. If you create an object with certain data and then pass it to a function, the function does not know and does not need to know what data the object was created with. The object can be treated as a magic black box that spits out answers. If you use a functional language like Haskell or Lisp, closures provide much the same function.
It also allows for sane state management - rather than a giant grab-bag of global variables that might get modified who-knows-where, the object's variables are protected from unknown modifications. This can come in very handy during debugging, when you need to know when a data value is (for example) being set to something invalid. If it's a global, you would have to put print statements all over the place or trust in a debugger. If you use an object, you can put in many less statements (or breakpoints, whatever). Obviously, the closer access to an attribute is controlled within the object, the fewer "chokepoints" there will be for the data.
Note that this does not mean that you should hide all attributes behind get_ functions. I see this annoying pattern a lot in Java programmers, because they've had OOP slammed down their throats in a language that doesn't support properties. If the purpose of your class is to simply contain a bunch of data with no behavior, just make all the attributes public. Please do not ever write classes that look like this (might not compile, been a while since I used Java, but you get the idea):
Behavior Sharing
Say you've got two classes for printing that share some of code, but have parts that are different:
By moving the common code into a shared parent class, you can reduce code duplication. This is probably easiest to see with an example, so I'll use a hypothetical printing library. This library can handle both laser printers and ink printers:
Note the duplicated code. This problem can be reduced if you move the common code into a parent class, and then inherit from it:
The dynamic (and some static) languages above do a very nice job of hiding implementation details for variables. However, if you want to get anywhere with C or C++ you must learn how pointers and arrays operate. The two are one and the same, so I will cover both at once.
First, some definitions. A pointer is a variable that points to another variable. An array is like a list, but has a size fixed when it is created. Within the computer, memory can be treated as a massive one-dimensional array. When you create a variable (say, an integer) the computer will calculate the amount of memory required, allocate it from the available memory, and give you a pointer to that memory size. Anything you want can be stored in there, not just what type you originally asked for, but don't get crazy or people will hate you and your code. While in dynamic languages variables are "labels", in a static language variables are "boxes".
There is another important difference between an array and a list. An array can only hold one type of object (specifically, each cell in an array is of a fixed size equal to the size required for each instance of the array's contained type). For example, say you were to construct an array of 4 32-bit integers. Each cell of the array will be 32 bits long, for a total of 128 bits. You can construct a list such as [1, "Hello", ["lol", "wow"]], but an array can only hold whatever the array was created for.
Here's an example of using pointers to manipulate integer variables in C:
Now, to tie all this into arrays. An array is actually treated, internally, as a pointer. You can dereference it, modify it, whatever. What's more, you can treat normal pointers like arrays! An example:
Since I'm still more or less a beginner myself, I'll need someone to PM me some notes on that. Is threading even appropriate for a beginner programming thread, though?
What is a CRE language?
Maybe they mean CLR?
Its implementation of threads is clearly more fundamental but its very doable on C or C++ if you're in the right C frame of thought. And 99.9% of the time a simple fork()s in C works just as well and will likely be faster since you don't have to go through the added overhead of the framework. C# is nice and all but it always feels really bulky whenever I use it and I can't really imagine using it for something so performance sensitive that threading must be used instead of simple forking.
Of course, I get to use the FUBAR'd proprietary language developed in the 70s (or technically its 2nd generation descendant, the other half is its early 90s fourth generation descendant, also proprietary). Therefore I probably shouldn't criticizing perfectly reasonable languages like C#.
This is a problem with how we're teaching programming in the US. About the most complicated thing that should be done in an introductory course is Towers of Hanoi.
QEDMF xbl: PantsB G+
You should probably include something about allocation here. And multidimensional arrays. Oh and casting.
Something like: But I allocate my memory idiosyncratically (I'd been using malloc for arrays for a year before someone pointed out I should be using calloc). And sorry if my rusty C code is f'ed up I'm not by a compiler to check.
Oh and this would be a decent place to go into standard error output. And from there you get to files pretty easily.
edit:
Frustration rant - I miss C. That is a fucking elegant language. Its mysteries are deep and its truth powerful. This is the crap I get to code in
"O"^txn.class,FIRST^txn.urn,
DO{@Next(txn.urn),txn.urn'>LAST IF{@RA @GET.BATCH,1^?(B).BJAX,
IF{'BAR.BCH.urn 1^?(B).BJAERR[account,txn.urn,"NO BATCH on BYR"];
@BAR.BCH.status'="POSTED" 1^?(B).BJAERR[account,txn.urn,BAR.BCH.urn,"NOT POSTED"];
@txn.amount+?(B).BJAAMT[@txn.type,@bar.status]^?(B).BJAAMT[@txn.type,@bar.status]}}}};
RA
IF{@txn.type="A";@txn.type="R"}
GET.BATCH
@BAR.BCH.number.x[@txn.bch.date,@txn.bch]^BAR.BCH.urn
QEDMF xbl: PantsB G+
The lack of syntax coloring makes it hard to read though. And the php tags made it look atrocious.
Polymorphism Made Simple
So, what is polymorphism? Simply put, it's that objects remember what they are and behave accordingly, even when they're referenced through a parent class.
For example, let's say we make a Mammal class, with a function Speak that doesn't return anything:
Now, let's make some child classes depicting other animals:
Now, we'll create an ArrayList of Mammals, then ask them to speak.
The label will now say:
Woof
Meow
Oink
Hi, I'm Bob.
As you're already pointing out, I called each of the elements in the example as Mammals, though, not as their specific child class. But because of polymorphism, eash of those Mammals remembered what they were, and called their specific version of the Speak function.
There are two more types of loops used in modern programming languages that you'll see. The first is called a do-while loop, and is used when you want a while loop to execute at least once.
In the above example, you will have x equal to 2, but y equal to 1. This is because the while statement is evaluated at the start of the while loop, but at the end of the do-while loop.
The other form of loop is a relative newcomer, only seen in newer languages and addon libraries for older OO languages like C++. It's called a foreach loop, and is used to run a function across all elements of a collection (like an array).
This will add 3 to each element in the array, giving us [4, 5, 6, 7, 8].
Doing this with a for loop is much more work:
Note that the syntax of the foreach loop is much simpler than that of the for loop.
Could also explain it uses an iterator, and what that is.
Actually, foreach doesn't use an iterator.
Actually, it does in the CLR languages (really enumerator here). It only unrolls to a 'for loop' on intrinsic types.
There are actually two ways to repeat code - iteration, where we loop over and over through a piece of code; and recursion, where we call a function inside of itself. Let's take a look at Nightslyr's Fibonacci function:
This is an example of a recursive function. If you look at the bottom, you can see that to get any value past the first 2, we call the function inside of itself. That said, we could write the same function iteratively:
That will do the exact same thing as the recursive example. However, it is a bit more complicated.
Now, here's the kicker - which one would you use to calculate, say...the 5th Fibonacci number? How about the 25th? I would use the recursive function to get the first, but the iterative one to get the 25th. The reason is simple - while the iterative function is more complex, it always remains at the same level of complexity. In comparison, watch what happens when we start looking at the mechanism of the recursive function:
fib(2) = fib(1) + fib(0) = 1 + 1 = 2
fib(3) = fib(2) + fib(1) = (fib(1) + fib(0)) + fib(0) = (1 + 1) + 1 = 3
fib(4) = fib(3) + fib(2) = (fib(2) + fib(1)) + (fib(1) + fib(0)) = ((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0)) = ((1 + 1) + 1) + (1 + 1) = 5
And so on. As you can see, the recursive function increases in complexity in a geometric fashion, whereas the iterative version increases arithmetically.
Polymorphism is probably the central concept behind OOP, and one of the more difficult to fully grasp. Its also one of the few areas where different languages require fundamentally different designs depending on their implementation of inheritance.
Abstract Classes
Consider: What if you were using the above Mammal system. No animal is simply a "Mammal" and there is no "Mammal" noise to make when it speaks. The system should thus be prohibited from creating an instance of "Mammal" as this does not reflect reality.
While this may appear harmless in other examples it could lead to instability and security holes.
This is achievable through an "abstract class." Not there is no Constructor, nor is there any code behind Speak(). The lack of code behind Speak is optional, but by using the virtual keyword, any non-abstract subclass must implement Speak.
Time is running short (I want to bang out a few more things before 530 when I'm out of here), so forgive the pseudo-code here on out.
Multiple inheritance:
In some languages (C++, LISP, Python), a class can inherit from more than one class. Other languages (Java, C#, PHP) you can inherit obligations through more than one class if you use a specific type of abstract class called an "interface." The former is increasingly deprecated because (in part) of the diamond problem.
The above example could have "Mammal" as an interface if we removed the name attribute (or made it some combination of final, constant and/or static depending on the language).
Any vendor - a coke machine, a candy machine, a cigarette machine, or a robot bartender would have to implement those features.
There's more if anyone wants to tackle Final classes and probably more important the static concept, fire away.
Oh and Linked Lists. That should probably be covered in combination with recursion, right before Tower of Hanoi
QEDMF xbl: PantsB G+
What you will need: a Mac and Xcode Developer Tools. You can buy a Mac from your local Apple store and Xcode should be available online as well, some say it also comes on the installation DVD with most Macs.
Prerequisites: You should be familiar with object oriented concepts and programming in general, as these are universal things that may not be specific to Cocoa. If you already know C and at least one object oriented language such as C++ or Java, you will do well and learn fast as fuck.
I'll update this section here regularly with new stuff over time, so check back every once and a while because I can tell already I'm probably not going to write all this stuff in one sitting. If you have any questions PM me or ask in the thread (but I don't really keep up with every page of this thread).
So let's begin.
Part 1: Objective C 2.0
This language is what you will use to do your Cocoa programming. If I had to describe Objective-C, I would basically tell you it's C with powerful object oriented shit added to it. C is a complete subset of Objective-C, which means any Objective-C compiler will also compile pure C code; you can freely mix C, C++ and Objective-C code together in the same application without problems. This gives you a powerful advantage, because you have the ease of high level coding like with Java and C#, but you are not restricted to it all the time (so you could do some custom optimization).
Because of this, a good Objective-C programmer should also be a good C programmer.
In Objective-C there exist things called objects. Objects are basically structures that carry two things, variables and methods. An object is defined by a class. The class describes the format of the object, meaning it tells you what variables the object has and their types, and what methods the objects run and what they return. In Objective-C, a class is also used to allocate an object.
When you want an object to run a certain method, you send it a message. There is a certain format to sending a message to an object, it looks like this:
Notice this is dramatically different from some languages where you may write something like:
object.Function();
Well, it gets wierder. If you are sending messages with parameters, they start to look like this
It looks bizarre at first, the function being peppered with parameters all up inside it like that, but the end result is some very readable code. The format for the messages is defined of course when you write the classes.
In Objective-C there is also a variable of type id. An id variable stands for object identifier. You can think of an id as a pointer to any type of object. So if you see a method that returns a type "id", it means it returns a pointer to an object. Because an id can be any object type, you don't really know shit about it other than the fact that it IS an object.
A class is defined by two files: a header file (.h) and an implementation file (.m). Xcode generally creates both these files when you go to define a new class.
Here is an example of a class definition, in it's own file called noobert.h
And here is the implementation of that class, in a separate file called noobert.m
So now suppose we have this class called noobert, and we wish to create an object of type noobert.
We will need to create a variable, allocate memory for the noobert object, and then initialize it. It works like this (assuming all this code is a part of something larger):
Ok well I've talked about Objective-C this whole time and I actually haven't said anything about Cocoa yet so I'll have to continue later because I'm going to sleep.
I don't really know how much more I'll write about Objective-C, I mean I could basically go on forever, and I've only scratched the syntactic surface here. It's a simple language to learn though if you have the right background, so next update I'll show you how to start building applications right away, complete with full UI and stuff, no command line BS. Peace.
Part 2: Building a Cocoa Application
coming soon
update: in case anyone cares, I'll get to this eventually, sorry I'm just pretty loaded with work right now
waitin' on 'dis.
An abstract class can not be marked private. That would defeat the purpose of being inherited. It can be marked public or internal.
If a method must be implemented by sub classes (edit: i had weird wording here), it is marked abstract, such as your Speak() method. It is not a virtual method.
Abstract classes can certainly have a constructor and any other implementation that is seen in non-abstract classes.
An Interface is not an abstract class at all. It is a special type that defines a contract that the object that implements the interface is bound to uphold. There is not much else to it than that. Interfaces also can not define the accessor on it's members. IOW, you can not tell the implementer that they must set function Foo to private.
One important concept I have not yet seen discussed is the concept of immutability.
Ask some freakin' C questions
I second this sentiment.
Although I get the feeling we're getting a bit long in the tooth, old friend. Back in my days, I remember having to write assembly bitblt instructions by hand to work with SVGA graphics (640 x 480 x 16-bit colour!? WOW!!! I think my S3 video card had enough video memory to do 800 x 600 x 16-bit colour as well!). See, it was real mode on the x86 back then - I hadn't quite mastered protected mode, so I could only access 64k of video RAM at any time. Ahh, bank switching.
Remember EMS and XMS? You wanted more than 640k but didn't want to go into protected mode? EMS and XMS were the only real ways (well, there was that fake real mode with 32-bit flat memory addresses that you could get into, but that required you to remove memory managers like himem.sys and emm386, so it didn't feel that good).
Learning how to use DMA to pipe sound out to sound-blaster compatible cards.
Man, those were the days.
Now, you get callbacks and HALs and whatever else to do everything for you.
Times have changed, I say. Perhaps for the better, but I still remember the shock I had when I finally played a wav file through my speakers (okay, I had calculated the sample rate wrong, so it played about 4 times as fast or something - but still!).
Um, I kind of hate to say this, but while I do know everything you're talking about, I never had to deal with it.
It doesn't have to. Recursion can do Fibonacci just fine. Just have to go about it slightly differently:
Runs in nice linear time.
As an interesting exercise for anyone who's curious, try executing both my method and the previous recursive method of finding Fibonacci numbers. You will quickly see the difference in speed as you increase n.
In the Fibonacci example, you might do it like this:
The iterative solution that was proposed earlier is kind of an optimization of this, designed to save memory. Since only the last two entries of the array of used, only those are kept in variables.
I'm working in Eclipse. I've transferred my project files from my Vista laptop to my XP desktop. I fixed the reference file locations, etc etc.
When I try to start main(), My laptop runs the program fine, my desktop does not. Does anyone have any ideas because this is seriously pissing me off. Google hasn't been much help, apart from telling me that main.class is missing, and to set the classpath to fix it. I'm not sure if I'm setting it correctly (Configure Build Path > Classpath tab > Advanced > Enter Classpath Variable > Configure > New).
Seriously guys this is doing my head in :x
[edit]NEVER MIND, I don't know what the hell happened, but the error fixed itself and after correcting a typo it found the prerequisite DLLs and shit, now it's working all fine and dandy, yay.
1 - An abstract class can be private, both conceptually and in C#. I didn't intend to leave a private keyword on Mammal but that was incorrect for reasons other than inheritance.
2 - Just screwed up on virtual keyword, rusty as a I said.
3 - Abstract classes can have constructors, you're correct. Those constructors should not be directly accessible, however.
4 - Interfaces are absolutely abstract classes. Abstract classes are by definition those classes that can not be directly created, only classes that inherit from them. Interfaces are a subset of abstract classes conceptually and only really exist to deal with multiple inheritance.
QEDMF xbl: PantsB G+
Java classpath isn't set correctly. Always took me 20 minutes to figure out whenever I went back to Java at the start of a new semester
QEDMF xbl: PantsB G+
1. It can be, only internal to another class. True. We should probably find a better example than the link you provided, which is almost a proof of concept (bad design) example of it. I can only think of a single design reason for using an abstract class in this manner.
Either way, it *is* incorrect for inheritance because no types would have scope to it in that context. My point, although being wrong, was for you to correct your mistake so that others didn't repeat it.
3. It needs to be decided if we're going to discuss what *can* be done and what *should* be done. Public constructors are fine on abstract classes. They aren't the best as far as design goes, but they are correct. It wouldn't make much sense for a language to support abstract classes yet allow them to be instantiated just because you made the constructor accessible.
4. I completely disagree. Saying they are the same and then saying one is a subset of the other makes no sense to me. They function differently and provide different, yet closely related, purposes. Thinking they are the same is exactly why most people fail interview questions about the two.
Yeah see, I tried entering the 'jdk folder/lib' location into the Windows env variable section, I don't think Eclipse cares though. Spent an hour looking through Eclipse settings and saw nothing obvious. Somehow a reboot fixed the problem. It was a goddamn headache anyway.
Can someone give a clear explanation of the difference between abstract classes and interfaces, and perhaps an example of when you would want to use one and not the other? I'm still shaky on this topic, even after my C# course last semester.
The definition of an abstract class is one that can not be instantiated.
"Interfaces" only exist in languages that prohibit multiple inheritance. They exist explicitly because of the diamond problem. Intro courses don't teach it in these terms usually but the only reason they exist is to get some of the benefits of multiple inheritance while limiting the problems inherent by gimping some of the flexibility in the class (usually all virtual methods & only immutable/static attributes).
If you can come up with an interface example that could not be conceptually replaced by an abstract class in a system with multiple inheritance fire away. In the same way that an abstract class is a subset with restrictions of classes in general, interfaces are a subset of abstract classes.
QEDMF xbl: PantsB G+