MIDL Complex Types As Interface Method Parameters - midl

I would like to know if maybe there are some good solutions to handling complex types not importable into IDL. My biggest concern is using _m128 vector types for simmed instructions ie. XMVECTOR. __declspec is not recognized by the midl compiler so importing the __m128 data type is out of the question. I looked into using wire_marshal to do this but I think it needs to be aware of the typedef of the __m128 type. If there is a way I can foreword_declare XMVECTOR for use with wire_marshal I haven't the foggiest on how I would do so.
I have thought of hiding the type by encapsulating it which it will already be being that I am encapsulating data types for Reflection. I have played around with a few ideas here including inheriting from both COM and C++ interfaces. Nothing here looked too promising.
A lot of people have told me not to use COM and I honestly have spent a lot of hours not coding and just trying to figure this stuff out. My logic keeps seeing a whole lot of benefits to using COM and the alternatives including MyCOM look just as time consuming and riddled with problems. If this is my biggest problem with using COM should I keep moving foreword or are the solutions going to slow down this application, keeping in mind its reliance on graphical presentation and real time computational modeling? I am looking into doing stuff on scale of rendering farms or clouds or something of the sort... I talk big and I know I am noob so please, not trying to impress just looking to become informed ... I have done a lot of research!
thx,
BekaD:

Leaves a bit of a funny taste in my mouth :\
typedef XMVECTOR* PTR_XMVECTOR;
typedef struct _ARRAY_XMVECTOR {
unsigned int size_array;
[size_is(size_array*SIZE_OF_XMVECTOR)] PTR_XMVECTOR VECTOR_ARRAY;
} ARRAY_XMVECTOR;
typedef [wire_marshal(MARSHAL_AS)] ARRAY_XMVECTOR MY_VECTOR_ARRAY;
I would have edited it in or added it as a comment but probably the closest this thread will come to an answer... probably the obvious one .... sorry for answering my own question :/

Related

Object Orient Design Why we need composition for Bird class?

Recently I was asked a question in an interview to design a bird flight simulator.
I went ahead and thought of strategy pattern for the simulator class and attributes like air pressure, wind velocity etc. A method would take a bird object and time and would return x,y,z coordinates.
e.g.
class Simulator
attr_accesor :bird, :air_pressure, :wind_velocity
def map_coordinates(bird, time)
...
end
...
end
and then thought about bird class:
For the bird can fly/Not fly attribute I thought about a boolean variable which would be set at initialization time. For e.g:
class Bird
attr_accessor :weight, :wing_dimension, :canfly, :height....
def initialize(weight, wing_dimension, canfly, height)
#weight = weight
#wing_dimension = wing_dimension
#canfly = canfly
#height = height
end
end
My question is from OOD point of view, it says a Bird class should use composition and use a class to encapsulate the properties required in a class. https://www.safaribooksonline.com/library/view/head-first-design/0596007124/ch01.html
So, Do I really need a class to map the canfly behavior? Can't I just have a boolean field to be initialized in this case while creating the Bird object.
Why would not that be a good design?
If not, what's the best approach and why?
In terms of OOD it's important make a comparison between association/aggregation, inheritance, composition and use. In a composition relationship the class should create object instances using the method new of the class.
Bird class has associated particular weight and height, in terms of composition a bird has two wings and a peak, which maybe can be different classes. In Wing class, wing_dimension attribute should be included as an aggregation relationship, as weight and height in bird class.
class Bird
attr_accessor :weight, :height, :rightWing, :leftWing, :peak
def initialize(weight, height)
#weight = weight
#height = height
rightWing = Wing. new
leftWing = Wing. new
peak = Peak.new
end
end
In Simulator class, for example, if you'll want to design a fly simulator, this attribute needs to be common in different classes.
To sum up, if exists an inheritance relationship between a general class, for example "Animal" with bird and fly(insect), you can make an aggregation relationship in def, and canfly as an attrinute of Animal class.
class Simulator
attr_accesor :animal, :air_pressure, :wind_velocity
def map_coordinates(animal, time)
...
end
...
end
So, Do I really need a class to map the canfly behavior? Can't I just have a Boolean field to be initialized in this case while creating the Bird object?
Why would not that be a good design? If not, what's the best approach and why?
To your first question: "Do I really need...?" That is a really good
question. In terms of Object Oriented Design, that is the very question you need to be asking yourself. In fact, that is exactly how good design decisions are made.
The fact that you also arrived at a tentative solution "Can't I just...?" means that you have identified ONE small problem that you might solve with a binary solution. bool canfly ? true : false
Let's assume, that you have looked at the big picture. You imagine that your "SIMULATOR" will have all different kinds of birds, even birds
that cannot fly, as well as those TYPICAL birds that do.
And finally, you arrive at three other, really fantastic questions.
I can't help but wonder whether or not you pulled these questions straight out of an OOA & D textbook.
1) Why would not that be a good design?
2) What would be a better design?
3) Why would the second design be better than the first
OK, I am going to try my best here. I am going to attempt to make an illustration from your approach in asking these questions, and in the way that you did. Look at the tiny footprint that all of these questions make here, in comparison to the HUGE footprint it WILL make in my post, trying to fill in all of those blanks because you have no idea how many answers those questions could generate (nor do I). That just happens to be one of the answers. Man, I hope this doesn't turn into a sprawling mess.(that's another one)
I think first, I would like to clarify one very important distinction.
The nature of these questions is not the same as the nature of the questions you would expect to find answers to in an algebra textbook. Algebra is about HOW. I discovered that the WHY
doesn't really mean anything in Algebra until you get to Calculus.
Why not this way...What way should I...How is that way better...Why is that way better...? WHY should I even care? These are the kinds of questions you find answers to in a philosophy textbook. They are the appropriate kind for OOD as well because OOD is more of a philosophy than it is a "soft science." It is my opinion, and others hold that opinion, but some think otherwise. Does that sound concrete?
Interestingly enough, that is a term used in OOD to differentiate a derived class from an Abstract class or an Interface. It is the result, but it is NOT the design. In my opinion, understanding that first is as important, if not more, than any concrete design that some might try to pass off as a good answer.
Let me ask a question also. Would you rather have your tiny footprint in your code-base or my HUGE footprint there? Because you may do what you want, that is your choice. However, let me just point something out that might change your mind. I can create an Interface lets say, and I
might call it something like this.
public Interface IEveryPossibleFlyingOperationYouOrAnyoneElseMightImagine{}; And you would probably say: That is a ridiculously long and over descriptive naming convention you have there!!! To which I would reply: Yes, but you can't even imagine how many things that Interface covers....And besides, I only ever have to write it once, because then I can do this...
IEveryPossibleFlyingOperationYouOrAnyoneElseMightImagine fly;
Then I would put that tiny little fly (also an insect that just happens to fly by the way.) in my code-base. Then, I would close it up, and HOPEFULLY never have to open it again.
Furthermore, everything that belongs to that Interface, which you know nothing about, because it has been abstracted away, and loosely coupled with other things like it, for the purpose of possible future extension, will never break your code base. How could it? It's a tiny little fly.
You see how long this answer is, and it only scratches the surface of what you are actually asking here I assure you.
Now, I will try to give you something a little more concrete, though it will not be nearly enough to satisfy all of what you are asking here.
OOP, in general, is about a lot of things, this one thing, that I hope makes at least some sense, is a principle. If that principle is learned and followed, you will never have my footprint in your code-base.
The big mystery of what is behind that interface is something that your client will never have to even know about, but I assure you that the way it is put together makes it extremely versatile and adaptive, because I built it according to tried and proven principles and patterns that other people way smarter than me figured out.
Even they don't know all of the possibilities of this paradigm because there are too many to count. They don't care anyway because they are busy solving other design issues by mixing and matching principles and patterns solving really complex problems very simply.
Also, get this, the next time you set out to design something you can put that tiny little fly in that and use it there too, and there will ever be, only one place to go to maintain and improve all that is behind that tiny little fly.
I know this is probably not the answer you were looking for, or maybe you get it already, which would be awesome. It took me forever just to figure out what the hell an object even was...but once it clicked, with the help of a really smart professor, who showed me what I tried to show here; oh..
and a book called Gang of Four; then I was able to begin, and I only wish I understood it all too.
I think if you go back and look at that article, you will be able to figure out what the other answers are, I only answered the easy one(or tried). I looked at it, and all of the information is there. It might be that you just need to look at it in a slightly different way, but you will get it if you really want to know.
I'm sorry, but that is the best I can do, and be honest at the same time. If anyone tries to tell you HOW is the answer, instead of WHY, don't listen to them, because the likely don't understand it either, but not because it's hard. It would be because they didn't start out asking the right questions like you did here. I wish you well and hope that someone else comes along who can maybe explain it better than me. +1) For asking all the right questions!

Chess programming, Scala, JVM: How costly is dynamic dispatch? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
My aim is to write a basic chess playing AI. It doesn't need to be incredible, but I want it to play with some degree of competence against people with some level of familiarity with the game.
I have a trait called Piece which has abstract methods canMakeMove(m: Move, b: Board) and allMovesFrom(p: Position, b: Board). These methods are important to the program logic for obvious reasons, and are implemented by the concrete classes King, Queen, Pawn, Rook, Bishop, and Knight. Thus in other places, say for example in the code that determines whether or not a particular board has a King in check, these methods are called on values whose type is the abstract type Piece, (piece canMakeMove (..., ...)) so the actual method called is determined at runtime via dynamic dispatch.
I'm wondering if this is too costly for the purposes of a Chess AI program which is going to have to execute this code many times. After looking around online and reading some more about chess programming I've found that the most common representation of a chess board is not like my Vector[Vector[Option[Piece]] but an int matrix ('bit board') that likely uses a switch statement on the values in the board to accomplish the effect that I'm currently relying on dynamic dispatch to achieve. Will this prevent my AI from reaching viable performance level?
I will suggest in this answer that you are subject to a common pitfall in programming.
There is one very important wisdom that I learned from my colleagues, and it has proven its worth to me time and time again:
Only solve problems when they occur, and not any sooner.
Keep in mind that there have been chess programs and chess computers around for a long, long time.
There were even chess programs on the C64, and there were those tiny travel chess computers that were embedded in the chess board, so you could carry them around easily.
Those systems had far less resources than your present day computer by several orders of magnitude.
If you had a similar algorithm as the one that was running on those old systems, and that algorithm was implemented in Scala, with dynamic dispatch, generous vectors instead of bit arrays et cetera, they would still be faster than they were on the older hardware from the past days.
Still, writing even a moderate search heuristic for the chess problem is a colossal task for a single developer.
When faced with a colossal task, one intuitively tends to look for the first bit of the problem that one feels competent in solving, in hopes that this will then naturally lead to the next little problem that you can solve, and so on, eventually leading to a full solution to the colossal problem. Divide and conquer.
However, my personal experience tells me that this is not a good way to tackle bigger programming problems.
Usually, if you follow this path, you end up with a really, really optimized representation of the chess board, consuming only very little memory, and optimized for runtime as much as possible.
And then you're stuck. You have put all your energy into this, you're really proud of your great chessboard class, and somehow it's really dissatisfying that you feel no step closer to actually have a working chess AI.
That's where the rule that I mentioned in the beginning comes in handy.
In short: Don't optimize. Yet. You can still optimize later, if it's necessary.
Instead, do the following:
Make a class or trait that represents a chessboard.
Leave it empty in the beginning - no methods or members.
Do the same with the types representing pieces, board positions, moves etc.
Then, when you start implementing the chess AI, fill in those types with methods. But only add the methods that you really need, and only when you need them, and not any single method more than that.
Prefer to use traits in the beginning, as you can later on produce more optimized versions of a trait, if necessary.
In that way, try to get as soon as you can to the first version of your chess AI that does something interesting.
It's up to you to define what "interesting" means in this context.
It's okay if the first version of the chess AI is crappy, and loses every game because it makes really bad decisions.
It should just have that one single thing: It should do something that you find at least remotely interesting.
Then, identify the top problem that you have with your chess AI.
Think about how to solve it, come up with a plan that solves only that one problem, in the simplest way that you can possibly imagine, even if your programmer instincts tell you to do something more complex.
Resist the urge to delve into complexity fast, because the most complex code that you write will eventually turn out to be your biggest problem, and also the most inflexible part of your code base.
Short, simple, almost stupid steps towards a solution. Prototype a lot, create simple versions in a short time, and only optimize when needed.
As for the optimization - that's really not a problem.
For example, let's say that in the beginning you thought it's a good idea to define a board position like this:
case class Position(x:Int, y:Int)
Later on, you figure that it would have been a better choice to just use a tuple of ints to represent a board position. Simply substitute your previous definition with:
type Position = (Int, Int)
There you go. Do that change, compile the code, and the compile errors will show you all the places in the code that you need to adapt. It's not going to take very long to refactor this.
Even later down the line, you decide that since there are only 64 possible positions on the board, you can easily represent the position with a number in the range from 0 to 64 - reserving the number 64 for "off-board".
Again, that's an easy change:
type Position = Byte
Save, compile, fix the compile errors. Should not take longer than 15 minutes.
With this example, I want to illustrate that you shouldn't be afraid of optimizing later, waiting to solve problems only when they actually occur.
This will always require some refactoring, but the effort is usually not really worth mentioning.
I tend to think of this as "massaging the code".
Of course we know that junior programmers sometimes tend to write "spaghetti code" that is very hard to refactor later.
Maybe that's why there is a certain fear of late optimization that practically every developer knows, and the urge to optimize early.
The only real antidote against such "spaghetti code" is to go through this painful process several times. After a while, you will develop a very good intuition on how to write code that can be optimized and refactored easily.
This will match all the common programming wisdoms, like separation of concerns, short methods, encapsulation and so on.
At this point, I would recommend the book "Clean Code" as an excellent guideline.
Some more tips:
See your program as a bridge. You stand on one side of the bridge, starting off with nothing. On the far end, there is your vision - a decent chess AI. Between the ends, there is a gap. Your program will be the bridge. Don't start by putting all your energy into optimizing the very first brick that you put in your bridge. A bridge with just one perfect brick won't hold. Build a prototype bridge first - crappy, but it connects the two ends. When you have that, it's easier to enhance the crappy bridge step by step.
Abstract all the functionality into traits and classes. Be wary of code repetitions - when you find a bug or need to do a refactoring, repetitious code can be a neck breaker.
Don't be afraid to write code that doesn't look smart, as long as the code is simple and solves the problem. Bonus points for code that reads well and looks almost like an intuitive description of the algorithm.
Keep your methods short. One to six lines.
Make sure that your code doesn't nest too deeply - everyone with a bit of Scala experience should be able to understand what your code is doing.
It can be a good thing to spend some time in order to find good names for your concepts. Maybe there are even some standards of naming certain parts of a chess AI. It's good to do a bit of research first.
While you are researching, see if there are some Scala/Java libraries available that you can use, for important parts of your problem. You can still replace the libraries with your own implementations later, but in the beginning, using the knowledge of other people can give you a jump start into creating your first, prototype version "bridge". Everything that will help you close the "gap" quickly is good.
Don't think of your code as something eternal, perfect, unchangeable. Maybe you have the ambition to write the best representation of a chess board in Scala ever. Don't do that. Eternal, perfect code cannot be refactored or changed easily. Code that can be refactored easily is really good code. Refactoring code is 50% of what a programmer does.
Jump into automated testing. For Scala, using the scalatest library can be a good choice. Use a tool like SBT that will run all the automated tests on every build. If you have certain assumptions about the classes you write, hardcode those assumptions into automated tests. It will feel a little stupid and redundant at first. But the first time that one of your automated tests show you the cause of a bug that would otherwise have been very hard to find, all the time to write those automated tests will have paid out.
An advanced topic about automated testing is code coverage. You can use a tool that will generate a coverage report, how much of your code is covered by automated tests. From my own experience, I would recommend jacoco4sbt.
And finally, the mandatory citation: "Optimization is the root of all evil." - There is a lot of wisdom in this one.
Good luck, and a whole lot of fun!

Objective-C Data Structures (Building my own DAWG)

After not programming for a long, long time (20+ years) I'm trying to get back into it. My first real attempt is a Scrabble/Words With Friends solver/cheater (pick your definition). I've built a pretty good engine, but it's solves the problems through brute force instead of efficiency or elegance. After much research, it's pretty clear that the best answer to this problem is a DAWG or CDWAG. I've found a few C implementations our there and have been able to leverage them (search times have gone from 1.5s to .005s for the same data sets).
However, I'm trying to figure out how to do this in pure Objective-C. At that, I'm also trying to make it ARC compliant. And efficient enough for an iPhone. I've looked quite a bit and found several data structure libraries (i.e. CHDataStructures ) out there, but they are mostly C/Objective-C hybrids or they are not ARC compliant. They rely very heavily on structs and embed objects inside of the structs. ARC doesn't really care for that.
So - my question is (sorry and I understand if this was tl;dr and if it seems totally a newb question - just can't get my head around this object stuff yet) how do you program classical data structures (trees, etc) from scratch in Objective-C? I don't want to rely on a NS[Mutable]{Array,Set,etc}. Does anyone have a simple/basic implementation of a tree or anything like that that I can crib from while I go create my DAWG?
Why shoot yourself in the foot before you even started walking?
You say you're
trying to figure out how do this in pure Objective-C
yet you
don't want to rely on a NS[Mutable]{Array,Set,etc}
Also, do you want to use ARC, or do you not want to use ARC? If you stick with Objective-C then go with ARC, if you don't want to use the Foundation collections, then you're probably better off without ARC.
My suggestion: do use NS[Mutable]{Array,Set,etc} and get your basic algorithm working with ARC. That should be your first and only goal, everything else is premature optimization. Especially if your goal is to "get back into programming" rather than writing the fastest possible Scrabble analyzer & solver. If you later find out you need to optimize, you have some working code that you can analyze for bottlenecks, and if need be, you can then still replace the Foundation collections.
As for the other libraries not being ARC compatible: you can pretty easily make them compatible if you follow some rules set by ARC. Whether that's worthwhile depends a lot on the size of the 3rd party codebase.
In particular, casting from void* to id and vice versa requires a bridged cast, so you would write:
void* pointer = (__bridge void*)myObjCObject;
Similarly, if you flag all pointers in C structs as __unsafe_unretained you should be able to use the C code as is. Even better yet: if the C code can be built as a static library, you can build it with ARC turned off and only need to fix some header files.

Suggested content for a lunch-time "Introduction to Scala" talk

I'm going to be giving a short (30-40 mins) lunch-time talk on Scala to technical staff at my company. I'd like some suggestions for what would be the most appropriate content. Most people attending will have experience in Java and/or C# (plus various other languages).
What are the key things to cover? I'd like to give a brief introduction to the Scala syntax so that people don't feel lost when looking at code examples. I'll also cover some of the history behind the language and its designers. What would help people get the most out of the talk?
People are almost certainly coming to talk to get an answer to the question, "Why should I use Scala?" Anything you can provide to help them answer that will be valuable.
Keep the discussion of the history and the personalities behind Scala to a minimum.
A whirlwind tour of the syntax is useful, but keep it short.
Spend a good chunk of the talk demonstrating examples and comparisons to Java. Show cases where Scala shines. You should literally be running and executing code so that people get a real, hands-on feel for how things work.
Make sure to cover weaknesses, too! Provide an objective and balanced overview.
I gave a similar talk - mostly to those with a Java background. I felt that taking a piece of real Java (about 30 lines) and iteratively adding scala features worked pretty well. The 30 lines of Java eventually ended up as 6 (six!) of scala. The point being (of course) that 6 lines are more readable and maintainable than 30.
I converted the scala to line-by-line Java equivalent and then introduced:
Type inference
Option
Closures
Pattern-matching (on lists)
Type aliases
Tail recursion
I found that this segment took quite a long time because the audience were very interested in the minutiae of scala's syntax (especially around function-expressions). Before undertaking the pattern-matching bit, I had a slide explaining the various things you could use in a match.
Tough. One has to balance the new and the familiar. For instance:
Talk about traits, how they differ from interfaces and multiple inheritance. Note that most methods in all of Scala collections can actually be found on the trait Traversable, which has a single abstract method: foreach.
Speak of functions and partial functions, show map/filter/foreach, and how they make use of functions.
Talk about pattern matching -- show how unapply is used to enable representation independence, while at the same time case classes make the common case easy.
Above all AVOID any topic that might be difficult to understand quickly, or you may waste time on them. For example of great topics I wouldn't talk about: self types, variance, for-comprehensions.
Pick more topics than you have time for. Let the public steer the conversation towards the topcis they are more interested in. If anyone starts to boggle down a topic too much, say you'll be pleased to explain it in more details later, and ask if they would mind if you moved to another topic. On the other hand, if everyone seems to be picking up on one thing in particular, stay with it. Otherwise, it might feel like you want to hide something.
I gave a presentation on re-writing Java classes in Scala. It has lots of examples of Java -> Scala and (hopefully) makes the gains obvious. Feel free to borrow any content you want... presentation took 1hr 10minutes so you might want to cut some stuff out.
Presentation: http://www.colinhowe.co.uk/downloads/rewriting-java-in-scala.ppt
Video: http://skillsmatter.com/podcast/java-jee/re-writing-java-classes-in-scala-and-making-your-code-lovely
You could do worse than running through Jonas Bonér's presentation, Pragmatic Real-World Scala. Perhaps skip some advanced topics in there on different applications of traits and self-type annotations.

How do you go from an abstract project description to actual code?

Maybe its because I've been coding around two semesters now, but the major stumbling block that I'm having at this point is converting the professor's project description and requirements to actual code. Since I'm currently in Algorithms 101, I basically do a bottom-up process, starting with a blank whiteboard and draw out the object and method interactions, then translate that into classes and code.
But now the prof has tossed interfaces and abstract classes into the mix. Intellectually, I can recognize how they work, but am stubbing my toes figuring out how to use these new tools with the current project (simulating a web server).
In my professors own words, mapping the abstract description to Java code is the real trick. So what steps are best used to go from English (or whatever your language is) to computer code? How do you decide where and when to create an interface, or use an abstract class?
So what steps are best used to go from English (or whatever your language is) to computer code?
Experience is what teaches you how to do this. If it's not coming naturally yet (and don't feel bad if it doesn't, because it takes a long time!), there are some questions you can ask yourself:
What are the main concepts of the system? How are they related to each other? If I was describing this to someone else, what words and phrases would I use? These thoughts will help you decide what classes are useful to think about.
What sorts of behaviors do these things have? Are there natural dependencies between them? (For example, a LineItem isn't relevant or meaningful without the context of an Order, nor is an Engine much use without a Car.) How do the behaviors affect the state of the other objects? Do they communicate with each other, and if so, in what way? These thoughts will help you develop the public interfaces of your classes.
That's just the tip of the iceberg, of course. For more about this thought process in general, see Eric Evans's excellent book, Domain-Driven Design.
How do you decide where and when to create an interface, or use an abstract class?
There's no hard and fast prescriptions; again, experience is the best guide here. That said, there's certainly some rules of thumb you can follow:
If several unrelated or significantly different object types all provide the same kind of functionality, use an interface. For example, if the Steerable interface has a Steer(Vector bearing) method, there may be lots of different things that can be steered: Boats, Airplanes, CargoShips, Cars, et cetera. These are completely unrelated things. But they all share the common interface of being able to be steered.
In general, try to favor an interface instead of an abstract base class. This way you can define a single implementation which implements N interfaces. In the case of Java, you can only have one abstract base class, so you're locked into a particular inheritance hierarchy once you say that a class inherits from another one.
Whenever you don't need implementation from a base class, definitely favor an interface over an abstract base class. This would also be handy if you're operating in a language where inheritance doesn't apply. For example, in C#, you can't have a struct inherit from a base class.
In general...
Read a lot of other people's code. Open source projects are great for that. Respect their licenses though.
You'll never get it perfect. It's an iterative process. Don't be discouraged if you don't get it right.
Practice. Practice. Practice.
Research often. Keep tackling more and more challenging projects / designs. Even if there are easy ones around.
There is no magic bullet, or algorithm for good design.
Nowadays I jump in with a design I believe is decent and work from that.
When the time is right I'll implement understanding the result will have to refactored ( rewritten ) sooner rather than later.
Give this project your best shot, keep an eye out for your mistakes and how things should've been done after you get back your results.
Keep doing this, and you'll be fine.
What you should really do is code from the top-down, not from the bottom-up. Write your main function as clearly and concisely as you can using APIs that you have not yet created as if they already existed. Then, you can implement those APIs in similar fashion, until you have functions that are only a few lines long. If you code from the bottom-up, you will likely create a whole lot of stuff that you don't actually need.
In terms of when to create an interface... pretty much everything should be an interface. When you use APIs that don't yet exist, assume that every concrete class is an implementation of some interface, and use a declared type that is indicative of that interface. Your inheritance should be done solely with interfaces. Only create concrete classes at the very bottom when you are providing an implementation. I would suggest avoiding abstract classes and just using delegation, although abstract classes are also reasonable when two different implementations differ only slightly and have several functions that have a common implementation. For example, if your interface allows one to iterate over elements and also provides a sum function, the sum function is a trivial to implement in terms of the iteration function, so that would be a reasonable use of an abstract class. An alternative would be to use the decorator pattern in that case.
You might also find the Google Techtalk "How to Design a Good API and Why it Matters" to be helpful in this regard. You might also be interested in reading some of my own software design observations.
Also, for the coming future, you can keep in pipeline to read the basics on domain driven design to align yourself to the real world scenarios - it gives a solid foundation for requirements mapping to the real classes.